mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-12-29 09:29:23 +00:00
Compare commits
7 Commits
3.0.2
...
3fc1058491
| Author | SHA1 | Date | |
|---|---|---|---|
| 3fc1058491 | |||
| c3668e978b | |||
| 5a4a6d5710 | |||
| ed1d8beb2e | |||
| 881ede7d2a | |||
| 60d3d279e7 | |||
| 4b84518dbb |
@@ -1,5 +1,10 @@
|
|||||||
# TelegramBotAPI changelog
|
# TelegramBotAPI changelog
|
||||||
|
|
||||||
|
## 3.1.0
|
||||||
|
|
||||||
|
* `Core`:
|
||||||
|
* Add support of `custom emoji`s
|
||||||
|
|
||||||
## 3.0.2
|
## 3.0.2
|
||||||
|
|
||||||
**ALL OLD DEPRECATIONS HAVE BEEN REMOVED**
|
**ALL OLD DEPRECATIONS HAVE BEEN REMOVED**
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ kotlin.incremental=true
|
|||||||
kotlin.incremental.js=true
|
kotlin.incremental.js=true
|
||||||
|
|
||||||
library_group=dev.inmo
|
library_group=dev.inmo
|
||||||
library_version=3.0.2
|
library_version=3.1.0
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ javax-activation = "1.1.1"
|
|||||||
|
|
||||||
korlibs = "3.0.0"
|
korlibs = "3.0.0"
|
||||||
uuid = "0.5.0"
|
uuid = "0.5.0"
|
||||||
ktor = "2.0.3"
|
ktor = "2.1.0"
|
||||||
|
|
||||||
ksp = "1.7.10-1.0.6"
|
ksp = "1.7.10-1.0.6"
|
||||||
kotlin-poet = "1.12.0"
|
kotlin-poet = "1.12.0"
|
||||||
|
|
||||||
microutils = "0.12.0"
|
microutils = "0.12.1"
|
||||||
|
|
||||||
github-release-plugin = "2.4.1"
|
github-release-plugin = "2.4.1"
|
||||||
|
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
|
|||||||
@@ -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<CustomEmojiId>
|
||||||
|
): SimpleRequest<CustomEmojiSticker> {
|
||||||
|
override fun method(): String = "getCustomEmojiStickers"
|
||||||
|
override val resultDeserializer: DeserializationStrategy<CustomEmojiSticker>
|
||||||
|
get() = StickerSerializer as DeserializationStrategy<CustomEmojiSticker>
|
||||||
|
override val requestSerializer: SerializationStrategy<*>
|
||||||
|
get() = serializer()
|
||||||
|
}
|
||||||
@@ -40,6 +40,7 @@ data class CreateNewAnimatedStickerSet internal constructor(
|
|||||||
@SerialName(tgsStickerField)
|
@SerialName(tgsStickerField)
|
||||||
val sticker: FileId? = null,
|
val sticker: FileId? = null,
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
val containsMasks: Boolean? = null,
|
val containsMasks: Boolean? = null,
|
||||||
@SerialName(maskPositionField)
|
@SerialName(maskPositionField)
|
||||||
override val maskPosition: MaskPosition? = null
|
override val maskPosition: MaskPosition? = null
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ data class CreateNewStaticStickerSet internal constructor(
|
|||||||
@SerialName(pngStickerField)
|
@SerialName(pngStickerField)
|
||||||
val sticker: FileId? = null,
|
val sticker: FileId? = null,
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
val containsMasks: Boolean? = null,
|
val containsMasks: Boolean? = null,
|
||||||
@SerialName(maskPositionField)
|
@SerialName(maskPositionField)
|
||||||
override val maskPosition: MaskPosition? = null
|
override val maskPosition: MaskPosition? = null
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ data class CreateNewVideoStickerSet internal constructor(
|
|||||||
@SerialName(webmStickerField)
|
@SerialName(webmStickerField)
|
||||||
val sticker: FileId? = null,
|
val sticker: FileId? = null,
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
val containsMasks: Boolean? = null,
|
val containsMasks: Boolean? = null,
|
||||||
@SerialName(maskPositionField)
|
@SerialName(maskPositionField)
|
||||||
override val maskPosition: MaskPosition? = null
|
override val maskPosition: MaskPosition? = null
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
package dev.inmo.tgbotapi.types
|
package dev.inmo.tgbotapi.types
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.utils.BuiltinMimeTypes
|
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
|
typealias Identifier = Long
|
||||||
typealias MessageIdentifier = Long
|
typealias MessageIdentifier = Long
|
||||||
@@ -28,6 +35,11 @@ typealias GooglePlaceId = String
|
|||||||
typealias GooglePlaceType = String
|
typealias GooglePlaceType = String
|
||||||
typealias MembersLimit = Int
|
typealias MembersLimit = Int
|
||||||
typealias WebAppQueryId = String
|
typealias WebAppQueryId = String
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class CustomEmojiId(
|
||||||
|
val string: String
|
||||||
|
)
|
||||||
|
|
||||||
typealias Seconds = Int
|
typealias Seconds = Int
|
||||||
typealias MilliSeconds = Long
|
typealias MilliSeconds = Long
|
||||||
@@ -37,6 +49,36 @@ typealias UnixTimeStamp = LongSeconds
|
|||||||
typealias Meters = Float
|
typealias Meters = Float
|
||||||
typealias Degrees = Int
|
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<StickerType> {
|
||||||
|
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 degreesLimit = 1 .. 360
|
||||||
val horizontalAccuracyLimit = 0F .. 1500F
|
val horizontalAccuracyLimit = 0F .. 1500F
|
||||||
|
|
||||||
@@ -126,6 +168,8 @@ const val supportInlineQueriesField = "supports_inline_queries"
|
|||||||
const val textEntitiesField = "text_entities"
|
const val textEntitiesField = "text_entities"
|
||||||
const val entitiesField = "entities"
|
const val entitiesField = "entities"
|
||||||
const val stickerSetNameField = "set_name"
|
const val stickerSetNameField = "set_name"
|
||||||
|
const val customEmojiIdField = "custom_emoji_id"
|
||||||
|
const val customEmojiIdsField = "custom_emoji_ids"
|
||||||
const val premiumAnimationField = "premium_animation"
|
const val premiumAnimationField = "premium_animation"
|
||||||
const val stickerSetNameFullField = "sticker_set_name"
|
const val stickerSetNameFullField = "sticker_set_name"
|
||||||
const val slowModeDelayField = "slow_mode_delay"
|
const val slowModeDelayField = "slow_mode_delay"
|
||||||
@@ -290,6 +334,7 @@ const val tgsStickerField = "tgs_sticker"
|
|||||||
const val webmStickerField = "webm_sticker"
|
const val webmStickerField = "webm_sticker"
|
||||||
const val oldChatMemberField = "old_chat_member"
|
const val oldChatMemberField = "old_chat_member"
|
||||||
const val newChatMemberField = "new_chat_member"
|
const val newChatMemberField = "new_chat_member"
|
||||||
|
const val stickerTypeField = "sticker_type"
|
||||||
|
|
||||||
const val okField = "ok"
|
const val okField = "ok"
|
||||||
const val captionField = "caption"
|
const val captionField = "caption"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import kotlinx.serialization.encoding.Encoder
|
|||||||
data class StickerSurrogate(
|
data class StickerSurrogate(
|
||||||
val file_id: FileId,
|
val file_id: FileId,
|
||||||
val file_unique_id: FileUniqueId,
|
val file_unique_id: FileUniqueId,
|
||||||
|
val type: StickerType,
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val height: Int,
|
val height: Int,
|
||||||
val is_animated: Boolean? = null,
|
val is_animated: Boolean? = null,
|
||||||
@@ -21,23 +22,22 @@ data class StickerSurrogate(
|
|||||||
val thumb: PhotoSize? = null,
|
val thumb: PhotoSize? = null,
|
||||||
val emoji: String? = null,
|
val emoji: String? = null,
|
||||||
val set_name: StickerSetName? = null,
|
val set_name: StickerSetName? = null,
|
||||||
|
val premium_animation: File? = null,
|
||||||
val mask_position: MaskPosition? = null,
|
val mask_position: MaskPosition? = null,
|
||||||
val file_size: Long? = null,
|
val custom_emoji_id: CustomEmojiId? = null,
|
||||||
val premium_animation: File? = null
|
val file_size: Long? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO:: Serializer
|
// TODO:: Serializer
|
||||||
@Serializable(StickerSerializer::class)
|
@Serializable(StickerSerializer::class)
|
||||||
sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile {
|
sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile {
|
||||||
val emoji: String?
|
val emoji: String?
|
||||||
val maskPosition: MaskPosition?
|
|
||||||
val stickerSetName: StickerSetName?
|
val stickerSetName: StickerSetName?
|
||||||
val premiumAnimationFile: File?
|
|
||||||
|
|
||||||
val isAnimated
|
val isAnimated
|
||||||
get() = this is AnimatedSticker
|
get() = false
|
||||||
val isVideo
|
val isVideo
|
||||||
get() = this is VideoSticker
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
object StickerSerializer : KSerializer<Sticker> {
|
object StickerSerializer : KSerializer<Sticker> {
|
||||||
@@ -46,43 +46,90 @@ object StickerSerializer : KSerializer<Sticker> {
|
|||||||
override fun deserialize(decoder: Decoder): Sticker {
|
override fun deserialize(decoder: Decoder): Sticker {
|
||||||
val surrogate = StickerSurrogate.serializer().deserialize(decoder)
|
val surrogate = StickerSurrogate.serializer().deserialize(decoder)
|
||||||
|
|
||||||
return when {
|
return when (surrogate.type) {
|
||||||
surrogate.is_animated == true -> AnimatedSticker(
|
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_id,
|
||||||
surrogate.file_unique_id,
|
surrogate.file_unique_id,
|
||||||
surrogate.width,
|
surrogate.width,
|
||||||
surrogate.height,
|
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.thumb,
|
||||||
surrogate.emoji,
|
surrogate.emoji,
|
||||||
surrogate.set_name,
|
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
|
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<Sticker> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@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)
|
@SerialName(fileIdField)
|
||||||
override val fileId: FileId,
|
override val fileId: FileId,
|
||||||
@SerialName(fileUniqueIdField)
|
@SerialName(fileUniqueIdField)
|
||||||
@@ -110,13 +199,13 @@ data class SimpleSticker(
|
|||||||
override val stickerSetName: StickerSetName? = null,
|
override val stickerSetName: StickerSetName? = null,
|
||||||
@SerialName(premiumAnimationField)
|
@SerialName(premiumAnimationField)
|
||||||
override val premiumAnimationFile: File?,
|
override val premiumAnimationFile: File?,
|
||||||
@SerialName(maskPositionField)
|
|
||||||
override val maskPosition: MaskPosition? = null,
|
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null,
|
override val fileSize: Long? = null,
|
||||||
) : Sticker
|
) : RegularSticker
|
||||||
|
@Deprecated("Renamed", ReplaceWith("SimpleRegularSticker", "dev.inmo.tgbotapi.types.files.SimpleRegularSticker"))
|
||||||
|
typealias SimpleSticker = RegularSimpleSticker
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AnimatedSticker(
|
data class RegularAnimatedSticker(
|
||||||
@SerialName(fileIdField)
|
@SerialName(fileIdField)
|
||||||
override val fileId: FileId,
|
override val fileId: FileId,
|
||||||
@SerialName(fileUniqueIdField)
|
@SerialName(fileUniqueIdField)
|
||||||
@@ -133,13 +222,11 @@ data class AnimatedSticker(
|
|||||||
override val stickerSetName: StickerSetName? = null,
|
override val stickerSetName: StickerSetName? = null,
|
||||||
@SerialName(premiumAnimationField)
|
@SerialName(premiumAnimationField)
|
||||||
override val premiumAnimationFile: File?,
|
override val premiumAnimationFile: File?,
|
||||||
@SerialName(maskPositionField)
|
|
||||||
override val maskPosition: MaskPosition? = null,
|
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null,
|
override val fileSize: Long? = null,
|
||||||
) : Sticker
|
) : RegularSticker, AnimatedSticker
|
||||||
@Serializable
|
@Serializable
|
||||||
data class VideoSticker(
|
data class RegularVideoSticker(
|
||||||
@SerialName(fileIdField)
|
@SerialName(fileIdField)
|
||||||
override val fileId: FileId,
|
override val fileId: FileId,
|
||||||
@SerialName(fileUniqueIdField)
|
@SerialName(fileUniqueIdField)
|
||||||
@@ -156,8 +243,75 @@ data class VideoSticker(
|
|||||||
override val stickerSetName: StickerSetName? = null,
|
override val stickerSetName: StickerSetName? = null,
|
||||||
@SerialName(premiumAnimationField)
|
@SerialName(premiumAnimationField)
|
||||||
override val premiumAnimationFile: File?,
|
override val premiumAnimationFile: File?,
|
||||||
@SerialName(maskPositionField)
|
|
||||||
override val maskPosition: MaskPosition? = null,
|
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null,
|
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
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.types.message
|
package dev.inmo.tgbotapi.types.message
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.*
|
import dev.inmo.tgbotapi.types.message.textsources.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -11,7 +12,8 @@ internal data class RawMessageEntity(
|
|||||||
val length: Int,
|
val length: Int,
|
||||||
val url: String? = null,
|
val url: String? = null,
|
||||||
val user: User? = null,
|
val user: User? = null,
|
||||||
val language: String? = null
|
val language: String? = null,
|
||||||
|
val custom_emoji_id: CustomEmojiId? = null
|
||||||
) {
|
) {
|
||||||
internal val range by lazy {
|
internal val range by lazy {
|
||||||
offset until (offset + length)
|
offset until (offset + length)
|
||||||
@@ -50,6 +52,7 @@ internal fun RawMessageEntity.asTextSource(
|
|||||||
"underline" -> UnderlineTextSource(sourceSubstring, subPartsWithRegulars)
|
"underline" -> UnderlineTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"strikethrough" -> StrikethroughTextSource(sourceSubstring, subPartsWithRegulars)
|
"strikethrough" -> StrikethroughTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"spoiler" -> SpoilerTextSource(sourceSubstring, subPartsWithRegulars)
|
"spoiler" -> SpoilerTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
|
"custom_emoji" -> CustomEmojiTextSource(sourceSubstring, custom_emoji_id ?: error("For custom emoji custom_emoji_id should exists"), subPartsWithRegulars)
|
||||||
else -> RegularTextSource(sourceSubstring)
|
else -> RegularTextSource(sourceSubstring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +161,8 @@ internal fun TextSource.toRawMessageEntities(offset: Int = 0): List<RawMessageEn
|
|||||||
is UnderlineTextSource -> RawMessageEntity("underline", offset, length)
|
is UnderlineTextSource -> RawMessageEntity("underline", offset, length)
|
||||||
is StrikethroughTextSource -> RawMessageEntity("strikethrough", offset, length)
|
is StrikethroughTextSource -> RawMessageEntity("strikethrough", offset, length)
|
||||||
is SpoilerTextSource -> RawMessageEntity("spoiler", offset, length)
|
is SpoilerTextSource -> RawMessageEntity("spoiler", offset, length)
|
||||||
else -> null
|
is CustomEmojiTextSource -> RawMessageEntity("custom_emoji", offset, length)
|
||||||
|
is RegularTextSource -> null
|
||||||
}
|
}
|
||||||
) + if (this is MultilevelTextSource) {
|
) + if (this is MultilevelTextSource) {
|
||||||
subsources.toRawMessageEntities(offset)
|
subsources.toRawMessageEntities(offset)
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package dev.inmo.tgbotapi.types.message.textsources
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
|
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||||
|
import dev.inmo.tgbotapi.utils.internal.*
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see customEmoji
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
|
override val source: String,
|
||||||
|
val customEmojiId: CustomEmojiId,
|
||||||
|
override val subsources: TextSourcesList
|
||||||
|
) : MultilevelTextSource {
|
||||||
|
override val markdown: String by lazy { source.customEmojiMarkdown() }
|
||||||
|
override val markdownV2: String by lazy { source.customEmojiMarkdownV2() }
|
||||||
|
override val html: String by lazy { source.customEmojiHTML() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_API_USAGE")
|
||||||
|
inline fun customEmoji(emojiId: CustomEmojiId, parts: TextSourcesList) = CustomEmojiTextSource(parts.makeString(), emojiId, parts)
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun customEmoji(emojiId: CustomEmojiId, vararg parts: TextSource) = customEmoji(emojiId, parts.toList())
|
||||||
|
/**
|
||||||
|
* Without sharp (#)
|
||||||
|
*/
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun customEmoji(emojiId: CustomEmojiId, text: String) = customEmoji(emojiId, regular(text))
|
||||||
@@ -21,6 +21,7 @@ private val baseSerializers: Map<String, KSerializer<out TextSource>> = mapOf(
|
|||||||
"hashtag" to HashTagTextSource.serializer(),
|
"hashtag" to HashTagTextSource.serializer(),
|
||||||
"cashtag" to CashTagTextSource.serializer(),
|
"cashtag" to CashTagTextSource.serializer(),
|
||||||
"spoiler" to SpoilerTextSource.serializer(),
|
"spoiler" to SpoilerTextSource.serializer(),
|
||||||
|
"custom_emoji" to CustomEmojiTextSource.serializer(),
|
||||||
)
|
)
|
||||||
|
|
||||||
object TextSourceSerializer : TypedSerializer<TextSource>(TextSource::class, baseSerializers) {
|
object TextSourceSerializer : TypedSerializer<TextSource>(TextSource::class, baseSerializers) {
|
||||||
|
|||||||
@@ -1,25 +1,87 @@
|
|||||||
package dev.inmo.tgbotapi.types.stickers
|
package dev.inmo.tgbotapi.types.stickers
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.files.PhotoSize
|
import dev.inmo.tgbotapi.types.files.*
|
||||||
import dev.inmo.tgbotapi.types.files.Sticker
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class StickerSet(
|
sealed interface StickerSet {
|
||||||
@SerialName(nameField)
|
@SerialName(nameField)
|
||||||
val name: String,
|
val name: String
|
||||||
@SerialName(titleField)
|
@SerialName(titleField)
|
||||||
val title: String,
|
val title: String
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
val stickerType: StickerType
|
||||||
@SerialName(stickersField)
|
@SerialName(stickersField)
|
||||||
val stickers: List<Sticker>,
|
val stickers: List<Sticker>
|
||||||
@SerialName(isAnimatedField)
|
@SerialName(isAnimatedField)
|
||||||
val isAnimated: Boolean = false,
|
val isAnimated: Boolean
|
||||||
@SerialName(isVideoField)
|
@SerialName(isVideoField)
|
||||||
val isVideo: Boolean = false,
|
val isVideo: Boolean
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
val containsMasks: Boolean = false,
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
|
val containsMasks: Boolean
|
||||||
|
get() = this is MaskStickerSet
|
||||||
@SerialName(thumbField)
|
@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<RegularSticker>,
|
||||||
|
@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<MaskSticker>,
|
||||||
|
@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<CustomEmojiSticker>,
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ internal fun String.commandMarkdown(): String = command(String::toMarkdown)
|
|||||||
internal fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
|
internal fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
|
||||||
internal fun String.commandHTML(): String = command(String::toHtml)
|
internal fun String.commandHTML(): String = command(String::toHtml)
|
||||||
|
|
||||||
|
internal fun String.customEmojiMarkdown(): String = toMarkdown()
|
||||||
|
internal fun String.customEmojiMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
|
internal fun String.customEmojiHTML(): String = toHtml()
|
||||||
|
|
||||||
internal fun String.regularMarkdown(): String = toMarkdown()
|
internal fun String.regularMarkdown(): String = toMarkdown()
|
||||||
internal fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
|
internal fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
internal fun String.regularHtml(): String = toHtml()
|
internal fun String.regularHtml(): String = toHtml()
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ import dev.inmo.tgbotapi.types.message.textsources.BoldTextSource
|
|||||||
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.CashTagTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.CashTagTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.CodeTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.CodeTextSource
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.CustomEmojiTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.HashTagTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.HashTagTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.ItalicTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.ItalicTextSource
|
||||||
@@ -3427,6 +3428,15 @@ public inline fun TextSource.codeTextSourceOrThrow(): CodeTextSource = this as
|
|||||||
public inline fun <T> TextSource.ifCodeTextSource(block: (CodeTextSource) -> T): T? =
|
public inline fun <T> TextSource.ifCodeTextSource(block: (CodeTextSource) -> T): T? =
|
||||||
codeTextSourceOrNull() ?.let(block)
|
codeTextSourceOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TextSource.customEmojiTextSourceOrNull(): CustomEmojiTextSource? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.message.textsources.CustomEmojiTextSource
|
||||||
|
|
||||||
|
public inline fun TextSource.customEmojiTextSourceOrThrow(): CustomEmojiTextSource = this as
|
||||||
|
dev.inmo.tgbotapi.types.message.textsources.CustomEmojiTextSource
|
||||||
|
|
||||||
|
public inline fun <T> TextSource.ifCustomEmojiTextSource(block: (CustomEmojiTextSource) -> T): T? =
|
||||||
|
customEmojiTextSourceOrNull() ?.let(block)
|
||||||
|
|
||||||
public inline fun TextSource.eMailTextSourceOrNull(): EMailTextSource? = this as?
|
public inline fun TextSource.eMailTextSourceOrNull(): EMailTextSource? = this as?
|
||||||
dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.formatting
|
package dev.inmo.tgbotapi.extensions.utils.formatting
|
||||||
|
|
||||||
import dev.inmo.micro_utils.common.joinTo
|
import dev.inmo.micro_utils.common.joinTo
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.*
|
import dev.inmo.tgbotapi.types.message.textsources.*
|
||||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
@@ -510,3 +511,39 @@ inline fun EntitiesBuilder.underline(text: String) = add(dev.inmo.tgbotapi.types
|
|||||||
* Version of [EntitiesBuilder.underline] with new line at the end
|
* Version of [EntitiesBuilder.underline] with new line at the end
|
||||||
*/
|
*/
|
||||||
inline fun EntitiesBuilder.underlineln(text: String) = underline(text) + newLine
|
inline fun EntitiesBuilder.underlineln(text: String) = underline(text) + newLine
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, parts))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, parts: TextSourcesList) = customEmoji(customEmojiId, parts) + newLine
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji].
|
||||||
|
* Will reuse separator config from [buildEntities]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, buildEntities(separator, init)))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end.
|
||||||
|
* Will reuse separator config from [buildEntities]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, noinline init: EntitiesBuilderBody) = customEmoji(customEmojiId, init) + newLine
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, *parts))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, vararg parts: TextSource) = customEmoji(customEmojiId, *parts) + newLine
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, text: String) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, text))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, text: String) = customEmoji(customEmojiId, text) + newLine
|
||||||
|
|||||||
Reference in New Issue
Block a user