1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-06-12 12:55:27 +00:00

versions updates

This commit is contained in:
InsanusMokrassar 2020-08-18 12:50:11 +06:00
parent d4551490f7
commit 6013c3ba86
52 changed files with 335 additions and 241 deletions

View File

@ -2,6 +2,20 @@
## 0.28.0
### RC
**THIS VERSION CONTAINS BREAKING CHANGES**
* `Common`:
* Version updates:
* `Kotlin`: `1.3.72` -> `1.4.0`
* `Coroutines`: `1.3.8` -> `1.3.9`
* `Serialization`: `0.20.0` -> `1.0.0-RC`
* `Klock`: `1.11.14` -> `1.12.0`
* `UUID`: `0.1.1` -> `0.2.0`
* `Ktor`: `1.3.2` -> `1.3.2-1.4.0-rc`
* `buildMimeType` function now is cache-oriented getter which will save already got mime types into internal map
## 0.27.0
* `Common`:

View File

@ -13,8 +13,8 @@ buildscript {
}
plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
project.version = "$library_version"
@ -31,7 +31,10 @@ repositories {
kotlin {
jvm()
js()
js {
browser()
nodejs()
}
sourceSets {
commonMain {

View File

@ -13,8 +13,8 @@ buildscript {
}
plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
project.version = "$library_version"
@ -31,7 +31,10 @@ repositories {
kotlin {
jvm()
js()
js {
browser()
nodejs()
}
sourceSets {
commonMain {

View File

@ -6,6 +6,6 @@ import kotlinx.serialization.json.Json
internal val nonstrictJsonFormat = Json {
isLenient = true
ignoreUnknownKeys = true
serializeSpecialFloatingPointValues = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
}

View File

@ -13,8 +13,8 @@ buildscript {
}
plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
project.version = "$library_version"
@ -31,7 +31,10 @@ repositories {
kotlin {
jvm()
js()
js {
browser()
nodejs()
}
sourceSets {
commonMain {

View File

@ -6,6 +6,6 @@ import kotlinx.serialization.json.Json
internal val nonstrictJsonFormat = Json {
isLenient = true
ignoreUnknownKeys = true
serializeSpecialFloatingPointValues = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
}

View File

@ -8,11 +8,11 @@ import kotlinx.serialization.json.JsonElement
/**
* @return Deserialize [source] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]
*/
fun Json.toTelegramUpdate(source: String) = parse(UpdateDeserializationStrategy, source)
fun Json.toTelegramUpdate(source: String) = decodeFromString(UpdateDeserializationStrategy, source)
/**
* @return Deserialize [source] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]
*/
fun Json.toTelegramUpdate(source: JsonElement) = fromJson(UpdateDeserializationStrategy, source)
fun Json.toTelegramUpdate(source: JsonElement) = decodeFromJsonElement(UpdateDeserializationStrategy, source)
/**
* @return Deserialize [this] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]. In fact,

View File

@ -45,8 +45,8 @@ fun Route.includeWebhookHandlingInRoute(
exceptionsHandler ?: {}
) {
val asJson =
nonstrictJsonFormat.parseJson(call.receiveText())
val update = nonstrictJsonFormat.fromJson(
nonstrictJsonFormat.parseToJsonElement(call.receiveText())
val update = nonstrictJsonFormat.decodeFromJsonElement(
UpdateDeserializationStrategy,
asJson
)

View File

@ -13,8 +13,8 @@ buildscript {
}
plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
project.version = "$library_version"
@ -31,15 +31,18 @@ repositories {
kotlin {
jvm()
js()
js {
browser()
nodejs()
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$kotlin_coroutines_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-properties-common:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-properties:$kotlin_serialisation_runtime_version"
api "com.soywiz.korlibs.klock:klock:$klock_version"
api "com.benasher44:uuid:$uuid_version"
@ -56,9 +59,6 @@ kotlin {
jvmMain {
dependencies {
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-properties:$kotlin_serialisation_runtime_version"
api "io.ktor:ktor-client:$ktor_version"
api "io.ktor:ktor-server:$ktor_version"
@ -76,12 +76,16 @@ kotlin {
jsMain {
dependencies {
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-properties-js:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$kotlin_coroutines_version"
api "io.ktor:ktor-client-js:$ktor_version"
}
}
jsTest {
dependencies {
implementation kotlin('test-junit')
implementation kotlin('test-js')
}
}
}
targets.all {

View File

@ -45,7 +45,7 @@ class KtorRequestsExecutor(
{ e ->
throw if (e is ClientRequestException) {
val content = e.response.readText()
val responseObject = jsonFormatter.parse(Response.serializer(), content)
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
newRequestException(
responseObject,
content,
@ -71,10 +71,10 @@ class KtorRequestsExecutor(
val response = statement?.execute() ?: throw IllegalArgumentException("Can't execute request: $request")
val content = response.receive<String>()
val responseObject = jsonFormatter.parse(Response.serializer(), content)
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
(responseObject.result?.let {
jsonFormatter.fromJson(request.resultDeserializer, it)
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
} ?: responseObject.parameters?.let {
val error = it.error
if (error is RetryAfterError) {

View File

@ -2,6 +2,9 @@ package com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.utils.StorageFile
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(InputFileSerializer::class)
sealed class InputFile {
@ -21,7 +24,7 @@ fun String.toInputFile() = FileId(this)
@Serializer(InputFile::class)
internal object InputFileSerializer : KSerializer<InputFile> {
override val descriptor: SerialDescriptor = PrimitiveDescriptor(FileId::class.toString(), PrimitiveKind.STRING)
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(FileId::class.toString(), PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: InputFile) = encoder.encodeString(value.fileId)
override fun deserialize(decoder: Decoder): FileId = FileId(decoder.decodeString())
}

View File

@ -12,6 +12,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.jsonArray
@Deprecated("Replaced and renamed", ReplaceWith("mediaCountInMediaGroup", "com.github.insanusmokrassar.TelegramBotAPI.types.mediaCountInMediaGroup"))
@ -71,9 +72,9 @@ data class SendMediaGroupData internal constructor(
) : DataRequest<List<MediaGroupMessage>>, SendMessageRequest<List<MediaGroupMessage>> {
@SerialName(mediaField)
private val convertedMedia: String
get() = jsonArray {
get() = buildJsonArray {
media.forEach {
+it.toJsonWithoutNulls(MediaGroupMemberInputMediaSerializer)
add(it.toJsonWithoutNulls(MediaGroupMemberInputMediaSerializer))
}
}.toString()

View File

@ -1,7 +1,9 @@
package com.github.insanusmokrassar.TelegramBotAPI.types
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonPrimitiveSerializer
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
@Serializable(ChatIdentifierSerializer::class)
sealed class ChatIdentifier
@ -40,7 +42,7 @@ fun String.toUsername(): Username = Username(this)
@Serializer(ChatIdentifier::class)
internal object ChatIdentifierSerializer : KSerializer<ChatIdentifier> {
override fun deserialize(decoder: Decoder): ChatIdentifier {
val id = JsonPrimitiveSerializer.deserialize(decoder)
val id = JsonPrimitive.serializer().deserialize(decoder)
return id.longOrNull ?.let {
ChatId(it)
} ?: id.content.let {

View File

@ -3,6 +3,9 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.ChatMember.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatMember.RawChatMember
import com.github.insanusmokrassar.TelegramBotAPI.types.User
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
interface ChatMember {
val user: User
@ -20,5 +23,5 @@ internal object ChatMemberDeserializationStrategy : DeserializationStrategy<Chat
override val descriptor: SerialDescriptor = RawChatMember.serializer().descriptor
override fun deserialize(decoder: Decoder): ChatMember = RawChatMember.serializer().deserialize(decoder).asChatMember
override fun patch(decoder: Decoder, old: ChatMember): ChatMember = throw UpdateNotSupportedException("ChatMember")
override fun patch(decoder: Decoder, old: ChatMember): ChatMember = error("ChatMember can't be patched")
}

View File

@ -3,10 +3,14 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQue
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.*
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializer(InlineQueryResult::class)
internal object InlineQueryResultSerializer : KSerializer<InlineQueryResult> {
override val descriptor: SerialDescriptor = SerialDescriptor(InlineQueryResult::class.toString(), PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor(InlineQueryResult::class.toString(), PolymorphicKind.OPEN)
override fun serialize(encoder: Encoder, value: InlineQueryResult) {
when(value) {
is InlineQueryResultArticle -> InlineQueryResultArticle.serializer().serialize(encoder, value)

View File

@ -3,10 +3,14 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InputMessageContent.*
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.abstracts.InputMessageContent
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializer(InputMessageContent::class)
internal object InputMessageContentSerializer : KSerializer<InputMessageContent> {
override val descriptor: SerialDescriptor = SerialDescriptor(InputMessageContent::class.toString(), PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor(InputMessageContent::class.toString(), PolymorphicKind.OPEN)
override fun serialize(encoder: Encoder, value: InputMessageContent) {
when (value) {
is InputContactMessageContent -> InputContactMessageContent.serializer().serialize(encoder, value)

View File

@ -18,7 +18,7 @@ data class InputMediaPhoto(
) : InputMedia, MediaGroupMemberInputMedia {
override val type: String = photoInputMediaType
override fun serialize(format: StringFormat): String = format.stringify(serializer(), this)
override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this)
@SerialName(mediaField)
val media: String = when (file) {
@ -27,7 +27,8 @@ data class InputMediaPhoto(
}
@Transient
override val arguments: Map<String, Any?> = Properties.storeNullable(serializer(), this)
@Deprecated("Marked as deprecated for removal in future updates", level = DeprecationLevel.ERROR)
override val arguments: Map<String, Any?> = error("Unsupported operation")
}
fun PhotoSize.toInputMediaPhoto(

View File

@ -1,10 +1,14 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializer(InputMedia::class)
internal object InputMediaSerializer : KSerializer<InputMedia> {
override val descriptor: SerialDescriptor = SerialDescriptor(InputMedia::class.toString(), PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor(InputMedia::class.toString(), PolymorphicKind.OPEN)
override fun serialize(encoder: Encoder, value: InputMedia) {
when (value) {
is InputMediaVideo -> InputMediaVideo.serializer().serialize(encoder, value)

View File

@ -5,6 +5,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
import com.github.insanusmokrassar.TelegramBotAPI.types.mediaField
import kotlinx.serialization.*
import kotlinx.serialization.properties.Properties
internal const val videoInputMediaType = "video"
@ -21,7 +22,7 @@ data class InputMediaVideo(
) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, MediaGroupMemberInputMedia {
override val type: String = videoInputMediaType
override fun serialize(format: StringFormat): String = format.stringify(serializer(), this)
override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this)
@SerialName(mediaField)
val media: String = when (file) {
@ -30,5 +31,6 @@ data class InputMediaVideo(
}
@Transient
override val arguments: Map<String, Any?> = Properties.storeNullable(serializer(), this)
@Deprecated("Marked as deprecated for removal in future updates", level = DeprecationLevel.ERROR)
override val arguments: Map<String, Any?> = error("Unsupported operation")
}

View File

@ -7,5 +7,6 @@ import kotlinx.serialization.StringFormat
@Serializable(MediaGroupMemberInputMediaSerializer::class)
interface MediaGroupMemberInputMedia : InputMedia, CaptionedOutput {
fun serialize(format: StringFormat): String
@Deprecated("Marked as deprecated for removal in future updates", level = DeprecationLevel.ERROR)
val arguments: Map<String, Any?>
}

View File

@ -3,11 +3,15 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia
import com.github.insanusmokrassar.TelegramBotAPI.types.typeField
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonObjectSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
@Serializer(MediaGroupMemberInputMedia::class)
internal object MediaGroupMemberInputMediaSerializer : KSerializer<MediaGroupMemberInputMedia> {
override val descriptor: SerialDescriptor = SerialDescriptor(MediaGroupMemberInputMedia::class.toString(), PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor(MediaGroupMemberInputMedia::class.toString(), PolymorphicKind.OPEN)
override fun serialize(encoder: Encoder, value: MediaGroupMemberInputMedia) {
when (value) {
is InputMediaPhoto -> InputMediaPhoto.serializer().serialize(encoder, value)
@ -16,11 +20,11 @@ internal object MediaGroupMemberInputMediaSerializer : KSerializer<MediaGroupMem
}
override fun deserialize(decoder: Decoder): MediaGroupMemberInputMedia {
val json = JsonObjectSerializer.deserialize(decoder)
val json = JsonObject.serializer().deserialize(decoder)
return when (json.getPrimitiveOrNull(typeField) ?.contentOrNull) {
photoInputMediaType -> nonstrictJsonFormat.fromJson(InputMediaPhoto.serializer(), json)
videoInputMediaType -> nonstrictJsonFormat.fromJson(InputMediaVideo.serializer(), json)
return when (json[typeField] ?.jsonPrimitive ?.contentOrNull) {
photoInputMediaType -> nonstrictJsonFormat.decodeFromJsonElement(InputMediaPhoto.serializer(), json)
videoInputMediaType -> nonstrictJsonFormat.decodeFromJsonElement(InputMediaVideo.serializer(), json)
else -> error("Illegal type of incoming MediaGroupMemberInputMedia")
}
}

View File

@ -1,6 +1,8 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
internal const val parseModeField = "parse_mode"

View File

@ -2,6 +2,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.types
import com.soywiz.klock.DateTime
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(TelegramDateSerializer::class)
data class TelegramDate(

View File

@ -5,7 +5,9 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.chat.extended.ExtendedPr
import com.github.insanusmokrassar.TelegramBotAPI.utils.PreviewFeature
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonObjectSerializer
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
@Serializable(UserSerializer::class)
sealed class User : PrivateChat
@ -69,24 +71,24 @@ data class ExtendedBot(
@Serializer(User::class)
internal object UserSerializer : KSerializer<User> {
override fun deserialize(decoder: Decoder): User {
val asJson = JsonObjectSerializer.deserialize(decoder)
val asJson = JsonObject.serializer().deserialize(decoder)
return when {
asJson.getPrimitiveOrNull(isBotField) ?.booleanOrNull != true -> nonstrictJsonFormat.fromJson(
asJson[isBotField] ?.jsonPrimitive ?.booleanOrNull != true -> nonstrictJsonFormat.decodeFromJsonElement(
CommonUser.serializer(),
asJson
)
else -> {
if ((asJson.get(canJoinGroupsField)
?: asJson.get(canReadAllGroupMessagesField)
?: asJson.get(supportInlineQueriesField)) != null
if ((asJson[canJoinGroupsField]
?: asJson[canReadAllGroupMessagesField]
?: asJson[supportInlineQueriesField]) != null
) {
nonstrictJsonFormat.fromJson(
nonstrictJsonFormat.decodeFromJsonElement(
ExtendedBot.serializer(),
asJson
)
} else {
nonstrictJsonFormat.fromJson(
nonstrictJsonFormat.decodeFromJsonElement(
CommonBot.serializer(),
asJson
)

View File

@ -1,6 +1,8 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.actions
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* Use BotAction objects realisations to notify user about bot actions

View File

@ -3,11 +3,14 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardB
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonElementSerializer
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
internal object InlineKeyboardButtonSerializer : KSerializer<InlineKeyboardButton> {
override val descriptor: SerialDescriptor = SerialDescriptor(
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor(
"com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardButtons.InlineKeyboardButton",
PolymorphicKind.SEALED
)
@ -26,10 +29,10 @@ internal object InlineKeyboardButtonSerializer : KSerializer<InlineKeyboardButto
}
override fun deserialize(decoder: Decoder): InlineKeyboardButton {
val json = JsonElementSerializer.deserialize(decoder)
val json = JsonElement.serializer().deserialize(decoder)
return (json as? JsonObject) ?.let { resolveSerializer(it) } ?.let {
nonstrictJsonFormat.fromJson(it, json)
nonstrictJsonFormat.decodeFromJsonElement(it, json)
} ?: UnknownInlineKeyboardButton("", json)
}
@ -42,7 +45,7 @@ internal object InlineKeyboardButtonSerializer : KSerializer<InlineKeyboardButto
is SwitchInlineQueryCurrentChatInlineKeyboardButton -> SwitchInlineQueryCurrentChatInlineKeyboardButton.serializer().serialize(encoder, value)
is URLInlineKeyboardButton -> URLInlineKeyboardButton.serializer().serialize(encoder, value)
is CallbackGameInlineKeyboardButton -> CallbackGameInlineKeyboardButton.serializer().serialize(encoder, value)
is UnknownInlineKeyboardButton -> JsonElementSerializer.serialize(encoder, value.rawData)
is UnknownInlineKeyboardButton -> JsonElement.serializer().serialize(encoder, value.rawData)
}
}
}

View File

@ -3,6 +3,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.buttons
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
@Serializable(KeyboardButtonSerializer::class)
@ -47,26 +49,26 @@ data class RequestPollKeyboardButton(
@Serializer(KeyboardButton::class)
internal object KeyboardButtonSerializer : KSerializer<KeyboardButton> {
override fun deserialize(decoder: Decoder): KeyboardButton {
val asJson = JsonElementSerializer.deserialize(decoder)
val asJson = JsonElement.serializer().deserialize(decoder)
return when {
asJson is JsonPrimitive -> SimpleKeyboardButton(asJson.content)
asJson is JsonObject && asJson.getPrimitiveOrNull(requestContactField) != null -> RequestContactKeyboardButton(
asJson.getPrimitive(textField).content
asJson is JsonObject && asJson[requestContactField] != null -> RequestContactKeyboardButton(
asJson[textField]!!.jsonPrimitive.content
)
asJson is JsonObject && asJson.getPrimitiveOrNull(requestLocationField) != null -> RequestLocationKeyboardButton(
asJson.getPrimitive(textField).content
asJson is JsonObject && asJson[requestLocationField] != null -> RequestLocationKeyboardButton(
asJson[textField]!!.jsonPrimitive.content
)
asJson is JsonObject && asJson.getObjectOrNull(requestPollField) != null -> RequestPollKeyboardButton(
asJson.getPrimitive(textField).content,
nonstrictJsonFormat.fromJson(
asJson is JsonObject && asJson[requestPollField] != null -> RequestPollKeyboardButton(
asJson[textField]!!.jsonPrimitive.content,
nonstrictJsonFormat.decodeFromJsonElement(
KeyboardButtonPollType.serializer(),
asJson.getObject(requestPollField)
asJson[requestPollField] ?.jsonObject ?: buildJsonObject { }
)
)
else -> UnknownKeyboardButton(
when (asJson) {
is JsonObject -> asJson.getPrimitive(textField).content
is JsonObject -> asJson[textField]!!.jsonPrimitive.content
is JsonArray -> ""
is JsonPrimitive -> asJson.content
},
@ -81,7 +83,7 @@ internal object KeyboardButtonSerializer : KSerializer<KeyboardButton> {
is RequestLocationKeyboardButton -> RequestLocationKeyboardButton.serializer().serialize(encoder, value)
is RequestPollKeyboardButton -> RequestPollKeyboardButton.serializer().serialize(encoder, value)
is SimpleKeyboardButton -> encoder.encodeString(value.text)
is UnknownKeyboardButton -> JsonElementSerializer.serialize(encoder, nonstrictJsonFormat.parseJson(value.raw))
is UnknownKeyboardButton -> JsonElement.serializer().serialize(encoder, nonstrictJsonFormat.parseToJsonElement(value.raw))
}
}
}

View File

@ -2,6 +2,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.buttons
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
@Serializable(KeyboardButtonPollTypeSerializer::class)
@ -25,11 +27,11 @@ object QuizKeyboardButtonPollType : KeyboardButtonPollType() {
@Serializer(KeyboardButtonPollType::class)
internal object KeyboardButtonPollTypeSerializer : KSerializer<KeyboardButtonPollType> {
override fun deserialize(decoder: Decoder): KeyboardButtonPollType {
val asJson = JsonElementSerializer.deserialize(decoder)
val asJson = JsonElement.serializer().deserialize(decoder)
val type = when (asJson) {
is JsonPrimitive -> asJson.content
else -> asJson.jsonObject.getPrimitive(typeField).content
else -> asJson.jsonObject[typeField] ?.jsonPrimitive ?.content ?: "absent"
}
return when (type) {
@ -43,7 +45,7 @@ internal object KeyboardButtonPollTypeSerializer : KSerializer<KeyboardButtonPol
* Crutch due to the fact that direct serialization of objects currently does not work perfectly
*/
override fun serialize(encoder: Encoder, value: KeyboardButtonPollType) {
JsonObjectSerializer.serialize(
JsonObject.serializer().serialize(
encoder,
JsonObject(
mapOf(

View File

@ -1,10 +1,14 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.buttons
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializer(KeyboardMarkup::class)
internal object KeyboardMarkupSerializer : KSerializer<KeyboardMarkup> {
override val descriptor: SerialDescriptor = SerialDescriptor(
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor(
KeyboardMarkup::class.toString(),
PolymorphicKind.OPEN
)

View File

@ -8,25 +8,29 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.chat.extended.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.JsonObjectSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
private val formatter = nonstrictJsonFormat
internal object PreviewChatSerializer : KSerializer<Chat> {
override val descriptor: SerialDescriptor = SerialDescriptor("PreviewChatSerializer", PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor("PreviewChatSerializer", PolymorphicKind.OPEN)
override fun deserialize(decoder: Decoder): Chat {
val decodedJson = JsonObjectSerializer.deserialize(decoder)
val decodedJson = JsonObject.serializer().deserialize(decoder)
val type = decodedJson.getPrimitive(typeField).content
val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?: error("Field $typeField must be presented, but absent in $decodedJson")
return when (type) {
"private" -> formatter.fromJson(PrivateChatImpl.serializer(), decodedJson)
"group" -> formatter.fromJson(GroupChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.fromJson(SupergroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.fromJson(ChannelChatImpl.serializer(), decodedJson)
"private" -> formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson)
"group" -> formatter.decodeFromJsonElement(GroupChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.decodeFromJsonElement(SupergroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.decodeFromJsonElement(ChannelChatImpl.serializer(), decodedJson)
else -> UnknownChatType(
formatter.fromJson(Long.serializer(), decodedJson.getPrimitive(chatIdField)).toChatId(),
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(),
decodedJson.toString()
)
}
@ -44,18 +48,19 @@ internal object PreviewChatSerializer : KSerializer<Chat> {
}
internal object ExtendedChatSerializer : KSerializer<ExtendedChat> {
override val descriptor: SerialDescriptor = SerialDescriptor("PreviewChatSerializer", PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor("PreviewChatSerializer", PolymorphicKind.OPEN)
override fun deserialize(decoder: Decoder): ExtendedChat {
val decodedJson = JsonObjectSerializer.deserialize(decoder)
val decodedJson = JsonObject.serializer().deserialize(decoder)
val type = decodedJson.getPrimitive(typeField).content
val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?: error("Field $typeField must be presented, but absent in $decodedJson")
return when (type) {
"private" -> formatter.fromJson(ExtendedPrivateChatImpl.serializer(), decodedJson)
"group" -> formatter.fromJson(ExtendedGroupChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.fromJson(ExtendedSupergroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.fromJson(ExtendedChannelChatImpl.serializer(), decodedJson)
"private" -> formatter.decodeFromJsonElement(ExtendedPrivateChatImpl.serializer(), decodedJson)
"group" -> formatter.decodeFromJsonElement(ExtendedGroupChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.decodeFromJsonElement(ExtendedSupergroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.decodeFromJsonElement(ExtendedChannelChatImpl.serializer(), decodedJson)
else -> throw IllegalArgumentException("Unknown type of chat")
}
}

View File

@ -1,6 +1,9 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.dice
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(DiceAnimationTypeSerializer::class)
sealed class DiceAnimationType {
@ -27,7 +30,7 @@ typealias UnknownDiceAnimationType = CustomDiceAnimationType
@Serializer(DiceAnimationType::class)
internal object DiceAnimationTypeSerializer : KSerializer<DiceAnimationType> {
override val descriptor: SerialDescriptor = PrimitiveDescriptor("DiceAnimationType", PrimitiveKind.STRING)
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("DiceAnimationType", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): DiceAnimationType {
return when (val type = decoder.decodeString()) {
CubeDiceAnimationType.emoji -> CubeDiceAnimationType

View File

@ -5,6 +5,9 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
import com.github.insanusmokrassar.TelegramBotAPI.types.message.RawMessage
import com.soywiz.klock.DateTime
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
interface Message {
val messageId: MessageIdentifier
@ -20,9 +23,10 @@ data class UnknownMessageType(
) : Message
internal class TelegramBotAPIMessageDeserializationStrategyClass<T> : DeserializationStrategy<T> {
override val descriptor: SerialDescriptor = SerialDescriptor("TelegramBotAPIMessageSerializer", PolymorphicKind.OPEN)
@InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor("TelegramBotAPIMessageSerializer", PolymorphicKind.OPEN)
override fun patch(decoder: Decoder, old: T): T = throw UpdateNotSupportedException("TelegramBotAPIMessageSerializer")
override fun patch(decoder: Decoder, old: T): T = error("TelegramBotAPIMessageSerializer")
@Suppress("UNCHECKED_CAST")
override fun deserialize(decoder: Decoder): T {
@ -34,6 +38,7 @@ internal object TelegramBotAPIMessageDeserializationStrategy
internal class TelegramBotAPIMessageDeserializeOnlySerializerClass<T : Message> : KSerializer<T> {
private val deserializer = TelegramBotAPIMessageDeserializationStrategyClass<T>()
@InternalSerializationApi
override val descriptor: SerialDescriptor
get() = deserializer.descriptor

View File

@ -7,8 +7,10 @@ import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import com.soywiz.klock.DateTime
import com.soywiz.klock.TimeSpan
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonObjectSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
sealed class ScheduledCloseInfo {
abstract val closeDateTime: DateTime
@ -101,11 +103,10 @@ data class UnknownPollType internal constructor(
val raw: JsonObject
) : Poll() {
@Transient
override val scheduledCloseInfo: ScheduledCloseInfo? = raw.getPrimitiveOrNull(
closeDateField
) ?.longOrNull ?.asExactScheduledCloseInfo ?: raw.getPrimitiveOrNull(
openPeriodField
) ?.longOrNull ?.asApproximateScheduledCloseInfo
override val scheduledCloseInfo: ScheduledCloseInfo? = (raw[closeDateField] ?: raw[openPeriodField])
?.jsonPrimitive
?.longOrNull
?.asApproximateScheduledCloseInfo
}
@Serializable(PollSerializer::class)
@ -150,8 +151,8 @@ internal object PollSerializer : KSerializer<Poll> {
get() = RawPoll.serializer().descriptor
override fun deserialize(decoder: Decoder): Poll {
val asJson = JsonObjectSerializer.deserialize(decoder)
val rawPoll = nonstrictJsonFormat.fromJson(RawPoll.serializer(), asJson)
val asJson = JsonObject.serializer().deserialize(decoder)
val rawPoll = nonstrictJsonFormat.decodeFromJsonElement(RawPoll.serializer(), asJson)
return when (rawPoll.type) {
quizPollType -> QuizPoll(
@ -218,7 +219,7 @@ internal object PollSerializer : KSerializer<Poll> {
closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L)
)
is UnknownPollType -> {
JsonObjectSerializer.serialize(encoder, value.raw)
JsonObject.serializer().serialize(encoder, value.raw)
return
}
}

View File

@ -3,6 +3,9 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.polls
import com.github.insanusmokrassar.TelegramBotAPI.types.textField
import com.github.insanusmokrassar.TelegramBotAPI.types.votesCountField
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(PollOptionSerializer::class)
sealed class PollOption {

View File

@ -14,6 +14,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
import com.github.insanusmokrassar.TelegramBotAPI.types.updateIdField
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject
@Serializable
internal data class RawUpdate constructor(

View File

@ -4,8 +4,10 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.update.RawUpdate
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonElementSerializer
interface Update {
val updateId: UpdateIdentifier
@ -21,7 +23,7 @@ data class UnknownUpdate(
typealias UnknownUpdateType = UnknownUpdate
internal object UpdateSerializerWithoutSerialization : KSerializer<Update> {
override val descriptor: SerialDescriptor = JsonElementSerializer.descriptor
override val descriptor: SerialDescriptor = JsonElement.serializer().descriptor
override fun deserialize(decoder: Decoder): Update = UpdateDeserializationStrategy.deserialize(decoder)
@ -36,17 +38,17 @@ internal object UpdateSerializerWithoutSerialization : KSerializer<Update> {
* @see kotlinx.serialization.json.Json.parse
*/
object UpdateDeserializationStrategy : DeserializationStrategy<Update> {
override val descriptor: SerialDescriptor = JsonElementSerializer.descriptor
override fun patch(decoder: Decoder, old: Update): Update = throw UpdateNotSupportedException("Update")
override val descriptor: SerialDescriptor = JsonElement.serializer().descriptor
override fun deserialize(decoder: Decoder): Update {
val asJson = JsonElementSerializer.deserialize(decoder)
return nonstrictJsonFormat.fromJson(
val asJson = JsonElement.serializer().deserialize(decoder)
return nonstrictJsonFormat.decodeFromJsonElement(
RawUpdate.serializer(),
asJson
).asUpdate(
asJson
)
}
override fun patch(decoder: Decoder, old: Update): Update = error("Unsupported operation")
}

View File

@ -3,40 +3,42 @@ package com.github.insanusmokrassar.TelegramBotAPI.utils
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.json.*
@Suppress("EXPERIMENTAL_API_USAGE")
internal val nonstrictJsonFormat = Json {
isLenient = true
ignoreUnknownKeys = true
serializeSpecialFloatingPointValues = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
}
fun <T: Any> T.toJsonWithoutNulls(serializer: SerializationStrategy<T>): JsonObject = toJson(serializer).withoutNulls()
fun <T: Any> T.toJson(serializer: SerializationStrategy<T>): JsonObject = nonstrictJsonFormat.toJson(
fun <T: Any> T.toJson(serializer: SerializationStrategy<T>): JsonObject = nonstrictJsonFormat.encodeToJsonElement(
serializer,
this
).jsonObject
fun JsonArray.withoutNulls(): JsonArray {
return jsonArray {
return buildJsonArray {
forEach {
when (it) {
is JsonObject -> +it.withoutNulls()
is JsonArray -> +it.withoutNulls()
is JsonPrimitive -> +it
is JsonObject -> add(it.withoutNulls())
is JsonArray -> add(it.withoutNulls())
is JsonPrimitive -> add(it)
}
}
}
}
fun JsonObject.withoutNulls(): JsonObject {
return json {
return buildJsonObject {
forEach { (k, v) ->
when (v) {
is JsonObject -> k to v.withoutNulls()
is JsonArray -> k to v.withoutNulls()
!is JsonNull -> k to v
is JsonObject -> put(k, v.withoutNulls())
is JsonArray -> put(k, v.withoutNulls())
!is JsonNull -> put(k, v)
JsonNull -> {
// do nothing
}
}
}
}

View File

@ -1,13 +1,36 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(MimeTypeSerializer::class)
expect class MimeType {
val raw: String
}
expect fun buildMimeType(raw: String): MimeType
private val mimesCache = mutableMapOf<String, MimeType>()
fun String.asMimeType() = buildMimeType(this)
internal expect fun createMimeType(raw: String): MimeType
fun buildMimeType(raw: String): MimeType = mimesCache.getOrPut(raw) {
createMimeType(raw)
}
@Serializer(MimeType::class)
internal expect object MimeTypeSerializer : KSerializer<MimeType>
internal object MimeTypeSerializer : KSerializer<MimeType> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("mimeType", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): MimeType {
val mimeType = decoder.decodeString()
return mimesCache.getOrPut(mimeType) {
createMimeType(mimeType)
}
}
override fun serialize(encoder: Encoder, value: MimeType) {
encoder.encodeString(value.raw)
}
}

View File

@ -1,6 +1,5 @@
package com.github.insanusmokrassar.TelegramBotAPI
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
val TestsJsonFormat = Json(JsonConfiguration.Stable)
val TestsJsonFormat = Json {}

View File

@ -2,12 +2,10 @@ package com.github.insanusmokrassar.TelegramBotAPI.types
import com.github.insanusmokrassar.TelegramBotAPI.TestsJsonFormat
import com.github.insanusmokrassar.TelegramBotAPI.types.actions.*
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.Serializable
import kotlin.test.Test
import kotlin.test.assertEquals
@ImplicitReflectionSerializer
class BotActionTests {
@Serializable
data class Example(
@ -33,10 +31,10 @@ class BotActionTests {
}
private fun checkBotActionSerializeDeserialize(example: Example) {
val stringified = TestsJsonFormat.stringify(Example.serializer(), example)
val stringified = TestsJsonFormat.encodeToString(Example.serializer(), example)
assertEquals("{\"botAction\":\"${example.botAction.actionName}\"}", stringified)
val deserialized = TestsJsonFormat.parse(Example.serializer(), stringified)
val deserialized = TestsJsonFormat.decodeFromString(Example.serializer(), stringified)
assertEquals(example, deserialized)
@ -44,7 +42,7 @@ class BotActionTests {
}
@Test
fun `BotAction correctly serialized and deserialized`() {
fun `BotAction_correctly_serialized_and_deserialized`() {
fun BotAction.example() = Example(this)
listOf(
TypingAction.example(),

View File

@ -1,43 +1,38 @@
package com.github.insanusmokrassar.TelegramBotAPI.types
import com.github.insanusmokrassar.TelegramBotAPI.TestsJsonFormat
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.Serializable
import kotlin.test.*
@ImplicitReflectionSerializer
private const val chatIdentifierChatId: Identifier = 123L
@ImplicitReflectionSerializer
private const val chatIdentifierLink = "tg://user?id=$chatIdentifierChatId"
@ImplicitReflectionSerializer
private const val testUsername = "@Example"
@ImplicitReflectionSerializer
class ChatIdentifierTests {
@Test
fun `Cast from Int to ChatId is working correctly`() {
fun `Cast_from_Int_to_ChatId_is_working_correctly`() {
val chatId = chatIdentifierChatId.toInt().toChatId()
assertEquals(chatIdentifierChatId, chatId.chatId)
}
@Test
fun `Cast from Byte to ChatId is working correctly`() {
fun `Cast_from_Byte_to_ChatId_is_working_correctly`() {
val chatId = chatIdentifierChatId.toByte().toChatId()
assertEquals(chatIdentifierChatId, chatId.chatId)
}
@Test
fun `Cast from Identifier to ChatId is working correctly`() {
fun `Cast_from_Identifier_to_ChatId_is_working_correctly`() {
val chatId = chatIdentifierChatId.toChatId()
assertEquals(chatIdentifierChatId, chatId.chatId)
}
@Test
fun `Creating link from ChatId is correct`() {
fun `Creating_link_from_ChatId_is_correct`() {
val chatId = chatIdentifierChatId.toChatId()
assertEquals(chatIdentifierLink, chatId.link)
}
@Test
fun `Cast from String to Username is working correctly`() {
fun `Cast_from_String_to_Username_is_working_correctly`() {
assertEquals(testUsername, testUsername.toUsername().username)
assertFails("Username creating must fail when trying to create from string which is not starting from @ symbol") {