1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-12-29 09:29:23 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
3fc1058491 start rework of stickers and stickersets 2022-08-13 00:02:48 +06:00
c3668e978b add support of custom emojis 2022-08-12 23:21:53 +06:00
5a4a6d5710 start 3.1.0 2022-08-12 22:42:47 +06:00
15 changed files with 438 additions and 62 deletions

View File

@@ -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**

View File

@@ -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.3 library_version=3.1.0

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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))

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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