1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-09-14 21:00:15 +00:00

add support of ChatBackground

This commit is contained in:
2024-05-09 21:54:24 +06:00
parent 7e986b2088
commit 97621bca67
12 changed files with 566 additions and 0 deletions

View File

@@ -0,0 +1,128 @@
package dev.inmo.tgbotapi.types
import dev.inmo.micro_utils.colors.common.HEXAColor
import dev.inmo.tgbotapi.utils.IntRGB24HEXAColorSerializer
import dev.inmo.tgbotapi.utils.extractDataAndJson
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
@ClassCastsIncluded
@Serializable(BackgroundFill.Companion::class)
sealed interface BackgroundFill {
val type: String
val colors: List<HEXAColor>
@Serializable
data class Solid(
@SerialName(colorField)
@Serializable(IntRGB24HEXAColorSerializer::class)
val color: HEXAColor
) : BackgroundFill {
@Transient
override val colors: List<HEXAColor> = listOf(color)
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type = "solid"
}
}
@Serializable
data class Gradient(
@SerialName(topColorField)
@Serializable(IntRGB24HEXAColorSerializer::class)
val topColor: HEXAColor,
@SerialName(bottomColorField)
@Serializable(IntRGB24HEXAColorSerializer::class)
val bottomColor: HEXAColor,
@SerialName(rotationAngleField)
val rotationAngle: Short,
) : BackgroundFill {
@Transient
override val colors: List<HEXAColor> = listOf(topColor, bottomColor)
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type = "gradient"
}
}
@Serializable
data class FreeformGradient(
@SerialName(colorsField)
override val colors: List<@Serializable(IntRGB24HEXAColorSerializer::class) HEXAColor>
) : BackgroundFill {
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type = "freeform_gradient"
}
}
@Serializable
data class Unknown(
override val type: String,
val raw: JsonElement?
) : BackgroundFill {
@SerialName(colorsField)
override val colors: List<HEXAColor> = emptyList()
}
companion object : KSerializer<BackgroundFill> {
@Serializable
class RawBackgroundFill private constructor(
@SerialName(typeField)
val type: String,
@Serializable(IntRGB24HEXAColorSerializer::class)
val color: HEXAColor? = null,
@SerialName(topColorField)
@Serializable(IntRGB24HEXAColorSerializer::class)
val topColor: HEXAColor? = null,
@SerialName(bottomColorField)
@Serializable(IntRGB24HEXAColorSerializer::class)
val bottomColor: HEXAColor? = null,
@SerialName(rotationAngleField)
val rotationAngle: Short? = null,
@SerialName(colorsField)
val colors: List<@Serializable(IntRGB24HEXAColorSerializer::class) HEXAColor>? = null
)
private val serializer = RawBackgroundFill.serializer()
override val descriptor: SerialDescriptor
get() = serializer.descriptor
override fun deserialize(decoder: Decoder): BackgroundFill {
val (raw, json) = decoder.extractDataAndJson(serializer)
return when (raw.type) {
Solid.type -> Solid(color = raw.color ?: return Unknown(raw.type, json))
Gradient.type -> Gradient(
topColor = raw.topColor ?: return Unknown(raw.type, json),
bottomColor = raw.bottomColor ?: return Unknown(raw.type, json),
rotationAngle = raw.rotationAngle ?: return Unknown(raw.type, json)
)
FreeformGradient.type -> FreeformGradient(raw.colors ?: return Unknown(raw.type, json))
else -> Unknown(raw.type, json)
}
}
override fun serialize(encoder: Encoder, value: BackgroundFill) {
when (value) {
is FreeformGradient -> FreeformGradient.serializer().serialize(encoder, value)
is Gradient -> Gradient.serializer().serialize(encoder, value)
is Solid -> Solid.serializer().serialize(encoder, value)
is Unknown -> value.raw ?.also {
JsonElement.serializer().serialize(encoder, it)
} ?: Unknown.serializer().serialize(encoder, value)
}
}
}
}

View File

@@ -0,0 +1,180 @@
package dev.inmo.tgbotapi.types
import dev.inmo.micro_utils.common.Progress
import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.utils.IntProgress100Serializer
import dev.inmo.tgbotapi.utils.extractDataAndJson
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonElement
@ClassCastsIncluded
@Serializable(BackgroundType.Companion::class)
sealed interface BackgroundType {
val type: String
sealed interface Movable : BackgroundType {
val isMoving: Boolean
}
sealed interface Dimmable : BackgroundType {
val darkThemeDimming: Progress
}
sealed interface Fillable : BackgroundType {
val fill: BackgroundFill
}
sealed interface WithDocument : BackgroundType {
val document: DocumentFile
}
@Serializable
data class Fill(
@SerialName(fillField)
override val fill: BackgroundFill,
@SerialName(darkThemeDimmingField)
@Serializable(IntProgress100Serializer::class)
override val darkThemeDimming: Progress
) : Fillable, Dimmable {
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type: String = "fill"
}
}
@Serializable
data class Wallpaper(
@SerialName(documentField)
override val document: DocumentFile,
@SerialName(darkThemeDimmingField)
@Serializable(IntProgress100Serializer::class)
override val darkThemeDimming: Progress,
@SerialName(isBlurredField)
val isBlurred: Boolean = false,
@SerialName(isMovingField)
override val isMoving: Boolean = false
) : WithDocument, Dimmable, Movable {
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type: String = "wallpaper"
}
}
@Serializable
data class Pattern(
@SerialName(documentField)
override val document: DocumentFile,
@SerialName(fillField)
override val fill: BackgroundFill,
@SerialName(intensityField)
@Serializable(IntProgress100Serializer::class)
val intensity: Progress,
@SerialName(isInvertedField)
val isInverted: Boolean = false,
@SerialName(isMovingField)
override val isMoving: Boolean = false
) : WithDocument, Fillable, Movable {
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type: String = "pattern"
}
}
@Serializable
data class ChatTheme(
@SerialName(themeNameField)
val themeName: String
): BackgroundType {
@EncodeDefault
@SerialName(typeField)
override val type: String = Companion.type
companion object {
const val type: String = "chat_theme"
}
}
@Serializable
data class Unknown(
@SerialName(typeField)
override val type: String,
val raw: JsonElement?
): BackgroundType
companion object : KSerializer<BackgroundType> {
@Serializable
data class RawBackgroundType(
val type: String,
@SerialName(fillField)
val fill: BackgroundFill? = null,
@SerialName(darkThemeDimmingField)
@Serializable(IntProgress100Serializer::class)
val darkThemeDimming: Progress? = null,
@SerialName(documentField)
val document: DocumentFile? = null,
@SerialName(isBlurredField)
val isBlurred: Boolean = false,
@SerialName(isMovingField)
val isMoving: Boolean = false,
@SerialName(intensityField)
@Serializable(IntProgress100Serializer::class)
val intensity: Progress? = null,
@SerialName(isInvertedField)
val isInverted: Boolean = false,
@SerialName(themeNameField)
val themeName: String? = null
)
override val descriptor: SerialDescriptor
get() = RawBackgroundType.serializer().descriptor
override fun deserialize(decoder: Decoder): BackgroundType {
val (raw, json) = decoder.extractDataAndJson(RawBackgroundType.serializer())
val unknown by lazy { Unknown(raw.type, json) }
return when (raw.type) {
Fill.type -> Fill(
raw.fill ?: return unknown,
raw.darkThemeDimming ?: return unknown
)
Wallpaper.type -> Wallpaper(
document = raw.document ?: return unknown,
darkThemeDimming = raw.darkThemeDimming ?: return unknown,
isBlurred = raw.isBlurred,
isMoving = raw.isMoving
)
Pattern.type -> Pattern(
document = raw.document ?: return unknown,
fill = raw.fill ?: return unknown,
intensity = raw.intensity ?: return unknown,
isInverted = raw.isInverted,
isMoving = raw.isMoving
)
ChatTheme.type -> ChatTheme(
raw.themeName ?: return unknown
)
else -> unknown
}
}
override fun serialize(encoder: Encoder, value: BackgroundType) {
when (value) {
is ChatTheme -> ChatTheme.serializer().serialize(encoder, value)
is Fill -> Fill.serializer().serialize(encoder, value)
is Wallpaper -> Wallpaper.serializer().serialize(encoder, value)
is Pattern -> Pattern.serializer().serialize(encoder, value)
is Unknown -> value.raw ?.also {
JsonElement.serializer().serialize(encoder, it)
} ?: Unknown.serializer().serialize(encoder, value)
}
}
}
}

View File

@@ -604,6 +604,20 @@ const val businessIntroField = "business_intro"
const val businessLocationField = "business_location"
const val businessOpeningHoursField = "business_opening_hours"
const val colorField = "color"
const val colorsField = "colors"
const val topColorField = "top_color"
const val bottomColorField = "bottom_color"
const val rotationAngleField = "rotation_angle"
const val fillField = "fill"
const val darkThemeDimmingField = "dark_theme_dimming"
const val isBlurredField = "is_blurred"
const val isInvertedField = "is_inverted"
const val isMovingField = "is_moving"
const val intensityField = "intensity"
const val themeNameField = "theme_name"
const val dayField = "day"
const val monthField = "month"
const val yearField = "year"

View File

@@ -0,0 +1,13 @@
package dev.inmo.tgbotapi.types.chat
import dev.inmo.tgbotapi.types.BackgroundType
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.CommonEvent
import dev.inmo.tgbotapi.types.typeField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ChatBackground(
@SerialName(typeField)
val type: BackgroundType
) : CommonEvent

View File

@@ -125,6 +125,9 @@ internal data class RawMessage(
// Boost added to groups
private val boost_added: ChatBoostAdded? = null,
// Chat background has been changed
private val chat_background_set: ChatBackground? = null,
// AutoDelete Message time changed
private val message_auto_delete_timer_changed: MessageAutoDeleteTimerChanged? = null,
@@ -260,6 +263,7 @@ internal data class RawMessage(
giveaway_winners is GiveawayPrivateResults -> giveaway_winners
giveaway_completed != null -> giveaway_completed
boost_added != null -> boost_added
chat_background_set != null -> chat_background_set
else -> null
}
}

View File

@@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.utils
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonElement
fun <T> Decoder.extractDataAndJson(serializer: DeserializationStrategy<T>): Pair<T, JsonElement?> {
return if (this is JsonDecoder) {
val raw = decodeJsonElement()
json.decodeFromJsonElement(serializer, raw) to raw
} else {
serializer.deserialize(this) to null
}
}

View File

@@ -0,0 +1,27 @@
package dev.inmo.tgbotapi.utils
import dev.inmo.micro_utils.common.Progress
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
object IntProgress100Serializer : KSerializer<Progress> {
override val descriptor: SerialDescriptor
get() = Int.serializer().descriptor
override fun deserialize(decoder: Decoder): Progress {
return Progress(
decoder.decodeInt(),
100
)
}
override fun serialize(encoder: Encoder, value: Progress) {
encoder.encodeInt(
value.of100Int
)
}
}

View File

@@ -0,0 +1,22 @@
package dev.inmo.tgbotapi.utils
import dev.inmo.micro_utils.colors.common.HEXAColor
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
object IntRGB24HEXAColorSerializer : KSerializer<HEXAColor> {
override val descriptor: SerialDescriptor
get() = Int.serializer().descriptor
override fun deserialize(decoder: Decoder): HEXAColor {
val raw = decoder.decodeInt()
return HEXAColor(raw.shl(2).toUInt() + 0xffu)
}
override fun serialize(encoder: Encoder, value: HEXAColor) {
encoder.encodeInt(value.rgbInt)
}
}