From 3fc1058491f46c63243b01cdcd1b755e09206097 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 13 Aug 2022 00:02:48 +0600 Subject: [PATCH] start rework of stickers and stickersets --- .../requests/get/GetCustomEmojiStickers.kt | 20 ++ .../stickers/CreateNewAnimatedStickerSet.kt | 1 + .../stickers/CreateNewStaticStickerSet.kt | 1 + .../stickers/CreateNewVideoStickerSet.kt | 1 + .../kotlin/dev/inmo/tgbotapi/types/Common.kt | 38 +++ .../dev/inmo/tgbotapi/types/files/Sticker.kt | 246 ++++++++++++++---- .../tgbotapi/types/stickers/StickerSet.kt | 88 ++++++- 7 files changed, 336 insertions(+), 59 deletions(-) create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/get/GetCustomEmojiStickers.kt diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/get/GetCustomEmojiStickers.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/get/GetCustomEmojiStickers.kt new file mode 100644 index 0000000000..3d144b32f8 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/get/GetCustomEmojiStickers.kt @@ -0,0 +1,20 @@ +package dev.inmo.tgbotapi.requests.get + +import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.files.CustomEmojiSticker +import dev.inmo.tgbotapi.types.files.StickerSerializer +import dev.inmo.tgbotapi.types.stickers.StickerSet +import kotlinx.serialization.* + +@Serializable +data class GetCustomEmojiStickers( + @SerialName(customEmojiIdsField) + val customEmojiIds: List +): SimpleRequest { + override fun method(): String = "getCustomEmojiStickers" + override val resultDeserializer: DeserializationStrategy + get() = StickerSerializer as DeserializationStrategy + override val requestSerializer: SerializationStrategy<*> + get() = serializer() +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewAnimatedStickerSet.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewAnimatedStickerSet.kt index 6571ac6829..554320a551 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewAnimatedStickerSet.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewAnimatedStickerSet.kt @@ -40,6 +40,7 @@ data class CreateNewAnimatedStickerSet internal constructor( @SerialName(tgsStickerField) val sticker: FileId? = null, @SerialName(containsMasksField) + @Deprecated("Will be removed soon due to its redundancy") val containsMasks: Boolean? = null, @SerialName(maskPositionField) override val maskPosition: MaskPosition? = null diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewStaticStickerSet.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewStaticStickerSet.kt index 85b0d5a514..056c7cd8aa 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewStaticStickerSet.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewStaticStickerSet.kt @@ -50,6 +50,7 @@ data class CreateNewStaticStickerSet internal constructor( @SerialName(pngStickerField) val sticker: FileId? = null, @SerialName(containsMasksField) + @Deprecated("Will be removed soon due to its redundancy") val containsMasks: Boolean? = null, @SerialName(maskPositionField) override val maskPosition: MaskPosition? = null diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewVideoStickerSet.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewVideoStickerSet.kt index c112c3498c..f979557599 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewVideoStickerSet.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/stickers/CreateNewVideoStickerSet.kt @@ -40,6 +40,7 @@ data class CreateNewVideoStickerSet internal constructor( @SerialName(webmStickerField) val sticker: FileId? = null, @SerialName(containsMasksField) + @Deprecated("Will be removed soon due to its redundancy") val containsMasks: Boolean? = null, @SerialName(maskPositionField) override val maskPosition: MaskPosition? = null diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt index cd3148226a..7698ed7051 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt @@ -1,7 +1,12 @@ package dev.inmo.tgbotapi.types import dev.inmo.tgbotapi.utils.BuiltinMimeTypes +import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import kotlin.jvm.JvmInline typealias Identifier = Long @@ -44,6 +49,36 @@ typealias UnixTimeStamp = LongSeconds typealias Meters = Float typealias Degrees = Int +@Serializable(StickerType.Serializer::class) +sealed interface StickerType { + val type: String + + @Serializable + object Regular : StickerType { override val type: String = "regular" } + @Serializable + object Mask : StickerType { override val type: String = "mask" } + @Serializable + object CustomEmoji : StickerType { override val type: String = "custom_emoji" } + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor = String.serializer().descriptor + + override fun deserialize(decoder: Decoder): StickerType { + return when (val type = decoder.decodeString()) { + Regular.type -> Regular + Mask.type -> Regular + CustomEmoji.type -> Regular + else -> error("Unknown type of emoji $type") + } + } + + override fun serialize(encoder: Encoder, value: StickerType) { + encoder.encodeString(value.type) + } + + } +} + val degreesLimit = 1 .. 360 val horizontalAccuracyLimit = 0F .. 1500F @@ -133,6 +168,8 @@ const val supportInlineQueriesField = "supports_inline_queries" const val textEntitiesField = "text_entities" const val entitiesField = "entities" const val stickerSetNameField = "set_name" +const val customEmojiIdField = "custom_emoji_id" +const val customEmojiIdsField = "custom_emoji_ids" const val premiumAnimationField = "premium_animation" const val stickerSetNameFullField = "sticker_set_name" const val slowModeDelayField = "slow_mode_delay" @@ -297,6 +334,7 @@ const val tgsStickerField = "tgs_sticker" const val webmStickerField = "webm_sticker" const val oldChatMemberField = "old_chat_member" const val newChatMemberField = "new_chat_member" +const val stickerTypeField = "sticker_type" const val okField = "ok" const val captionField = "caption" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt index d1f8e484b9..bb380507eb 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt @@ -14,6 +14,7 @@ import kotlinx.serialization.encoding.Encoder data class StickerSurrogate( val file_id: FileId, val file_unique_id: FileUniqueId, + val type: StickerType, val width: Int, val height: Int, val is_animated: Boolean? = null, @@ -21,23 +22,22 @@ data class StickerSurrogate( val thumb: PhotoSize? = null, val emoji: String? = null, val set_name: StickerSetName? = null, + val premium_animation: File? = null, val mask_position: MaskPosition? = null, - val file_size: Long? = null, - val premium_animation: File? = null + val custom_emoji_id: CustomEmojiId? = null, + val file_size: Long? = null ) // TODO:: Serializer @Serializable(StickerSerializer::class) sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile { val emoji: String? - val maskPosition: MaskPosition? val stickerSetName: StickerSetName? - val premiumAnimationFile: File? val isAnimated - get() = this is AnimatedSticker + get() = false val isVideo - get() = this is VideoSticker + get() = false } object StickerSerializer : KSerializer { @@ -46,43 +46,90 @@ object StickerSerializer : KSerializer { override fun deserialize(decoder: Decoder): Sticker { val surrogate = StickerSurrogate.serializer().deserialize(decoder) - return when { - surrogate.is_animated == true -> AnimatedSticker( + return when (surrogate.type) { + StickerType.Regular -> when { + surrogate.is_animated == true -> RegularAnimatedSticker( + surrogate.file_id, + surrogate.file_unique_id, + surrogate.width, + surrogate.height, + surrogate.thumb, + surrogate.emoji, + surrogate.set_name, + surrogate.premium_animation, + surrogate.file_size + ) + surrogate.is_video == true -> RegularVideoSticker( + surrogate.file_id, + surrogate.file_unique_id, + surrogate.width, + surrogate.height, + surrogate.thumb, + surrogate.emoji, + surrogate.set_name, + surrogate.premium_animation, + surrogate.file_size + ) + else -> RegularSimpleSticker( + surrogate.file_id, + surrogate.file_unique_id, + surrogate.width, + surrogate.height, + surrogate.thumb, + surrogate.emoji, + surrogate.set_name, + surrogate.premium_animation, + surrogate.file_size + ) + } + StickerType.Mask -> MaskSticker( surrogate.file_id, surrogate.file_unique_id, surrogate.width, surrogate.height, + surrogate.mask_position ?: error("For mask stickers field mask_position should be presented"), + surrogate.is_animated == true, + surrogate.is_video == true, surrogate.thumb, surrogate.emoji, surrogate.set_name, - surrogate.premium_animation, - surrogate.mask_position, - surrogate.file_size - ) - surrogate.is_video == true -> VideoSticker( - surrogate.file_id, - surrogate.file_unique_id, - surrogate.width, - surrogate.height, - surrogate.thumb, - surrogate.emoji, - surrogate.set_name, - surrogate.premium_animation, - surrogate.mask_position, - surrogate.file_size - ) - else -> SimpleSticker( - surrogate.file_id, - surrogate.file_unique_id, - surrogate.width, - surrogate.height, - surrogate.thumb, - surrogate.emoji, - surrogate.set_name, - surrogate.premium_animation, - surrogate.mask_position, surrogate.file_size ) + StickerType.CustomEmoji -> when { + surrogate.is_animated == true -> CustomEmojiAnimatedSticker( + surrogate.file_id, + surrogate.file_unique_id, + surrogate.width, + surrogate.height, + surrogate.custom_emoji_id ?: error("For mask stickers field mask_position should be presented"), + surrogate.thumb, + surrogate.emoji, + surrogate.set_name, + surrogate.file_size + ) + surrogate.is_video == true -> CustomEmojiVideoSticker( + surrogate.file_id, + surrogate.file_unique_id, + surrogate.width, + surrogate.height, + surrogate.custom_emoji_id ?: error("For mask stickers field mask_position should be presented"), + surrogate.thumb, + surrogate.emoji, + surrogate.set_name, + surrogate.file_size + ) + else -> CustomEmojiSimpleSticker( + surrogate.file_id, + surrogate.file_unique_id, + surrogate.width, + surrogate.height, + surrogate.custom_emoji_id ?: error("For mask stickers field mask_position should be presented"), + surrogate.thumb, + surrogate.emoji, + surrogate.set_name, + surrogate.file_size + ) + } } } @@ -92,8 +139,50 @@ object StickerSerializer : KSerializer { } +@Serializable(StickerSerializer::class) +sealed interface VideoSticker : Sticker { + override val isVideo: Boolean + get() = true +} +@Serializable(StickerSerializer::class) +sealed interface AnimatedSticker : Sticker { + override val isAnimated: Boolean + get() = true +} + +@Serializable(StickerSerializer::class) +sealed interface RegularSticker : Sticker { + val premiumAnimationFile: File? +} + @Serializable -data class SimpleSticker( +data class MaskSticker( + @SerialName(fileIdField) + override val fileId: FileId, + @SerialName(fileUniqueIdField) + override val fileUniqueId: FileUniqueId, + @SerialName(widthField) + override val width: Int, + @SerialName(heightField) + override val height: Int, + @SerialName(maskPositionField) + val maskPosition: MaskPosition, + @SerialName(isAnimatedField) + override val isAnimated: Boolean, + @SerialName(isVideoField) + override val isVideo: Boolean, + @SerialName(thumbField) + override val thumb: PhotoSize? = null, + @SerialName(emojiField) + override val emoji: String? = null, + @SerialName(stickerSetNameField) + override val stickerSetName: StickerSetName? = null, + @SerialName(fileSizeField) + override val fileSize: Long? = null, +) : Sticker + +@Serializable +data class RegularSimpleSticker( @SerialName(fileIdField) override val fileId: FileId, @SerialName(fileUniqueIdField) @@ -110,13 +199,13 @@ data class SimpleSticker( override val stickerSetName: StickerSetName? = null, @SerialName(premiumAnimationField) override val premiumAnimationFile: File?, - @SerialName(maskPositionField) - override val maskPosition: MaskPosition? = null, @SerialName(fileSizeField) override val fileSize: Long? = null, -) : Sticker +) : RegularSticker +@Deprecated("Renamed", ReplaceWith("SimpleRegularSticker", "dev.inmo.tgbotapi.types.files.SimpleRegularSticker")) +typealias SimpleSticker = RegularSimpleSticker @Serializable -data class AnimatedSticker( +data class RegularAnimatedSticker( @SerialName(fileIdField) override val fileId: FileId, @SerialName(fileUniqueIdField) @@ -133,13 +222,11 @@ data class AnimatedSticker( override val stickerSetName: StickerSetName? = null, @SerialName(premiumAnimationField) override val premiumAnimationFile: File?, - @SerialName(maskPositionField) - override val maskPosition: MaskPosition? = null, @SerialName(fileSizeField) override val fileSize: Long? = null, -) : Sticker +) : RegularSticker, AnimatedSticker @Serializable -data class VideoSticker( +data class RegularVideoSticker( @SerialName(fileIdField) override val fileId: FileId, @SerialName(fileUniqueIdField) @@ -156,8 +243,75 @@ data class VideoSticker( override val stickerSetName: StickerSetName? = null, @SerialName(premiumAnimationField) override val premiumAnimationFile: File?, - @SerialName(maskPositionField) - override val maskPosition: MaskPosition? = null, @SerialName(fileSizeField) override val fileSize: Long? = null, -) : Sticker +) : RegularSticker, VideoSticker + +@Serializable(StickerSerializer::class) +sealed interface CustomEmojiSticker : Sticker { + val customEmojiId: CustomEmojiId +} + +@Serializable +data class CustomEmojiSimpleSticker( + @SerialName(fileIdField) + override val fileId: FileId, + @SerialName(fileUniqueIdField) + override val fileUniqueId: FileUniqueId, + @SerialName(widthField) + override val width: Int, + @SerialName(heightField) + override val height: Int, + @SerialName(customEmojiIdField) + override val customEmojiId: CustomEmojiId, + @SerialName(thumbField) + override val thumb: PhotoSize? = null, + @SerialName(emojiField) + override val emoji: String? = null, + @SerialName(stickerSetNameField) + override val stickerSetName: StickerSetName? = null, + @SerialName(fileSizeField) + override val fileSize: Long? = null, +) : CustomEmojiSticker +@Serializable +data class CustomEmojiAnimatedSticker( + @SerialName(fileIdField) + override val fileId: FileId, + @SerialName(fileUniqueIdField) + override val fileUniqueId: FileUniqueId, + @SerialName(widthField) + override val width: Int, + @SerialName(heightField) + override val height: Int, + @SerialName(customEmojiIdField) + override val customEmojiId: CustomEmojiId, + @SerialName(thumbField) + override val thumb: PhotoSize? = null, + @SerialName(emojiField) + override val emoji: String? = null, + @SerialName(stickerSetNameField) + override val stickerSetName: StickerSetName? = null, + @SerialName(fileSizeField) + override val fileSize: Long? = null, +) : CustomEmojiSticker, AnimatedSticker +@Serializable +data class CustomEmojiVideoSticker( + @SerialName(fileIdField) + override val fileId: FileId, + @SerialName(fileUniqueIdField) + override val fileUniqueId: FileUniqueId, + @SerialName(widthField) + override val width: Int, + @SerialName(heightField) + override val height: Int, + @SerialName(customEmojiIdField) + override val customEmojiId: CustomEmojiId, + @SerialName(thumbField) + override val thumb: PhotoSize? = null, + @SerialName(emojiField) + override val emoji: String? = null, + @SerialName(stickerSetNameField) + override val stickerSetName: StickerSetName? = null, + @SerialName(fileSizeField) + override val fileSize: Long? = null, +) : CustomEmojiSticker, VideoSticker diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stickers/StickerSet.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stickers/StickerSet.kt index 84e13732bb..663a6e48bc 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stickers/StickerSet.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stickers/StickerSet.kt @@ -1,25 +1,87 @@ package dev.inmo.tgbotapi.types.stickers import dev.inmo.tgbotapi.types.* -import dev.inmo.tgbotapi.types.files.PhotoSize -import dev.inmo.tgbotapi.types.files.Sticker -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable +import dev.inmo.tgbotapi.types.files.* +import kotlinx.serialization.* @Serializable -data class StickerSet( +sealed interface StickerSet { @SerialName(nameField) - val name: String, + val name: String @SerialName(titleField) - val title: String, + val title: String + @SerialName(stickerTypeField) + val stickerType: StickerType @SerialName(stickersField) - val stickers: List, + val stickers: List @SerialName(isAnimatedField) - val isAnimated: Boolean = false, + val isAnimated: Boolean @SerialName(isVideoField) - val isVideo: Boolean = false, + val isVideo: Boolean @SerialName(containsMasksField) - val containsMasks: Boolean = false, + @Deprecated("Will be removed soon due to its redundancy") + val containsMasks: Boolean + get() = this is MaskStickerSet @SerialName(thumbField) - val thumb: PhotoSize? = null -) + val thumb: PhotoSize? +} + +@Serializable +data class RegularStickerSet( + @SerialName(nameField) + override val name: String, + @SerialName(titleField) + override val title: String, + @SerialName(stickersField) + override val stickers: List, + @SerialName(isAnimatedField) + override val isAnimated: Boolean = false, + @SerialName(isVideoField) + override val isVideo: Boolean = false, + @SerialName(thumbField) + override val thumb: PhotoSize? = null +) : StickerSet { + @SerialName(stickerTypeField) + @EncodeDefault + override val stickerType: StickerType = StickerType.Regular +} + +@Serializable +data class MaskStickerSet( + @SerialName(nameField) + override val name: String, + @SerialName(titleField) + override val title: String, + @SerialName(stickersField) + override val stickers: List, + @SerialName(isAnimatedField) + override val isAnimated: Boolean = false, + @SerialName(isVideoField) + override val isVideo: Boolean = false, + @SerialName(thumbField) + override val thumb: PhotoSize? = null +) : StickerSet { + @SerialName(stickerTypeField) + @EncodeDefault + override val stickerType: StickerType = StickerType.Mask +} + +@Serializable +data class CustomEmojiStickerSet( + @SerialName(nameField) + override val name: String, + @SerialName(titleField) + override val title: String, + @SerialName(stickersField) + override val stickers: List, + @SerialName(isAnimatedField) + override val isAnimated: Boolean = false, + @SerialName(isVideoField) + override val isVideo: Boolean = false, + @SerialName(thumbField) + override val thumb: PhotoSize? = null +) : StickerSet { + @SerialName(stickerTypeField) + @EncodeDefault + override val stickerType: StickerType = StickerType.CustomEmoji +}