1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-16 20:10:18 +00:00

add support of PostStory and EditStory

This commit is contained in:
2025-05-10 22:32:38 +06:00
parent effd12711f
commit e7367da3cb
9 changed files with 531 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
package dev.inmo.tgbotapi.requests.stories
import dev.inmo.tgbotapi.abstracts.TextedOutput
import dev.inmo.tgbotapi.requests.abstracts.BusinessRequest
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stories.PostStory
import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.types.StoryId
import dev.inmo.tgbotapi.types.activePeriodField
import dev.inmo.tgbotapi.types.areasField
import dev.inmo.tgbotapi.types.businessConnectionIdField
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.captionEntitiesField
import dev.inmo.tgbotapi.types.captionField
import dev.inmo.tgbotapi.types.contentField
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.asTextSources
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.types.postToChatPageField
import dev.inmo.tgbotapi.types.protectContentField
import dev.inmo.tgbotapi.types.stories.InputStoryContent
import dev.inmo.tgbotapi.types.stories.Story
import dev.inmo.tgbotapi.types.stories.StoryArea
import dev.inmo.tgbotapi.types.storyIdField
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
@Serializable
data class EditStory private constructor(
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId,
@SerialName(storyIdField)
val storyId: StoryId,
@SerialName(contentField)
val content: InputStoryContent,
@SerialName(captionField)
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val textEntities: List<RawMessageEntity>? = null,
@SerialName(areasField)
val areas: List<StoryArea> = emptyList(),
) : BusinessRequest.Multipart<Story>, TextedOutput {
override val textSources: List<TextSource>? by lazy {
textEntities ?.asTextSources(text ?: return@lazy null)
}
override val resultDeserializer: DeserializationStrategy<Story>
get() = Story.serializer()
override val mediaMap: Map<String, MultipartFile>
get() = mapOf(content.media)
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
constructor(
businessConnectionId: BusinessConnectionId,
storyId: StoryId,
content: InputStoryContent,
textSources: List<TextSource>,
areas: List<StoryArea> = emptyList(),
) : this(
businessConnectionId = businessConnectionId,
storyId = storyId,
content = content,
text = textSources.makeString(),
parseMode = null,
textEntities = textSources.toRawMessageEntities(),
areas = areas,
)
constructor(
businessConnectionId: BusinessConnectionId,
storyId: StoryId,
content: InputStoryContent,
text: String,
parseMode: ParseMode? = null,
areas: List<StoryArea> = emptyList(),
) : this(
businessConnectionId = businessConnectionId,
storyId = storyId,
content = content,
text = text,
parseMode = parseMode,
textEntities = null,
areas = areas,
)
constructor(
businessConnectionId: BusinessConnectionId,
storyId: StoryId,
content: InputStoryContent,
areas: List<StoryArea> = emptyList(),
) : this(
businessConnectionId = businessConnectionId,
storyId = storyId,
content = content,
text = null,
parseMode = null,
textEntities = null,
areas = areas,
)
override fun method(): String = "editStory"
}

View File

@@ -0,0 +1,129 @@
package dev.inmo.tgbotapi.requests.stories
import dev.inmo.tgbotapi.abstracts.TextedOutput
import dev.inmo.tgbotapi.requests.abstracts.BusinessRequest
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.types.activePeriodField
import dev.inmo.tgbotapi.types.areasField
import dev.inmo.tgbotapi.types.businessConnectionIdField
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.captionEntitiesField
import dev.inmo.tgbotapi.types.captionField
import dev.inmo.tgbotapi.types.contentField
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.asTextSources
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.types.postToChatPageField
import dev.inmo.tgbotapi.types.protectContentField
import dev.inmo.tgbotapi.types.stories.InputStoryContent
import dev.inmo.tgbotapi.types.stories.Story
import dev.inmo.tgbotapi.types.stories.StoryArea
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
@Serializable
data class PostStory private constructor(
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId,
@SerialName(contentField)
val content: InputStoryContent,
@SerialName(activePeriodField)
val activePeriod: Seconds,
@SerialName(captionField)
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val textEntities: List<RawMessageEntity>? = null,
@SerialName(areasField)
val areas: List<StoryArea> = emptyList(),
@SerialName(postToChatPageField)
val postToChatPage: Boolean = false,
@SerialName(protectContentField)
val protectContent: Boolean = false,
) : BusinessRequest.Multipart<Story>, TextedOutput {
override val textSources: List<TextSource>? by lazy {
textEntities ?.asTextSources(text ?: return@lazy null)
}
override val resultDeserializer: DeserializationStrategy<Story>
get() = Story.serializer()
override val mediaMap: Map<String, MultipartFile>
get() = mapOf(content.media)
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
constructor(
businessConnectionId: BusinessConnectionId,
content: InputStoryContent,
activePeriod: Seconds,
textSources: List<TextSource>,
areas: List<StoryArea> = emptyList(),
postToChatPage: Boolean = false,
protectContent: Boolean = false,
) : this(
businessConnectionId = businessConnectionId,
content = content,
activePeriod = activePeriod,
text = textSources.makeString(),
parseMode = null,
textEntities = textSources.toRawMessageEntities(),
areas = areas,
postToChatPage = postToChatPage,
protectContent = protectContent
)
constructor(
businessConnectionId: BusinessConnectionId,
content: InputStoryContent,
activePeriod: Seconds,
text: String,
parseMode: ParseMode? = null,
areas: List<StoryArea> = emptyList(),
postToChatPage: Boolean = false,
protectContent: Boolean = false,
) : this(
businessConnectionId = businessConnectionId,
content = content,
activePeriod = activePeriod,
text = text,
parseMode = parseMode,
textEntities = null,
areas = areas,
postToChatPage = postToChatPage,
protectContent = protectContent
)
constructor(
businessConnectionId: BusinessConnectionId,
content: InputStoryContent,
activePeriod: Seconds,
areas: List<StoryArea> = emptyList(),
postToChatPage: Boolean = false,
protectContent: Boolean = false,
) : this(
businessConnectionId = businessConnectionId,
content = content,
activePeriod = activePeriod,
text = null,
parseMode = null,
textEntities = null,
areas = areas,
postToChatPage = postToChatPage,
protectContent = protectContent
)
override fun method(): String = "postStory"
companion object {
const val ACTIVE_PERIOD_6_HOURS: Seconds = 6 * 3600
const val ACTIVE_PERIOD_12_HOURS: Seconds = 12 * 3600
const val ACTIVE_PERIOD_24_HOURS: Seconds = 24 * 3600 // 86400
const val ACTIVE_PERIOD_48_HOURS: Seconds = 48 * 3600 // 2 * 86400
}
}

View File

@@ -744,6 +744,10 @@ const val colorsField = "colors"
const val topColorField = "top_color"
const val bottomColorField = "bottom_color"
const val rotationAngleField = "rotation_angle"
const val contentField = "content"
const val activePeriodField = "active_period"
const val areasField = "areas"
const val postToChatPageField = "post_to_chat_page"
const val fillField = "fill"
const val darkThemeDimmingField = "dark_theme_dimming"

View File

@@ -6,6 +6,8 @@ import kotlinx.serialization.Serializable
@Serializable
data class StoryArea(
@SerialName(positionField)
val position: StoryAreaPosition,
@SerialName(typeField)
val type: StoryAreaType
)

View File

@@ -8,6 +8,7 @@ import dev.inmo.tgbotapi.utils.IntRGB24HEXAColorSerializer
import dev.inmo.tgbotapi.utils.LongRGBAFromHEXAColorSerializer
import dev.inmo.tgbotapi.utils.decodeDataAndJson
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@@ -18,6 +19,7 @@ import kotlin.jvm.JvmInline
sealed interface StoryAreaType {
val type: Type
@Serializable(TypeSerializer::class)
sealed interface Type {
val name: String
}
@@ -113,6 +115,26 @@ sealed interface StoryAreaType {
}
companion object : KSerializer<StoryAreaType> {
private object TypeSerializer : KSerializer<Type> {
override val descriptor: SerialDescriptor
get() = String.serializer().descriptor
override fun deserialize(decoder: Decoder): Type {
val raw = decoder.decodeString()
return when (raw) {
Location.name -> Location
SuggestedReaction.name -> SuggestedReaction
Link.name -> Link
Weather.name -> Weather
UniqueGift.name -> UniqueGift
else -> Unknown.Custom(raw)
}
}
override fun serialize(encoder: Encoder, value: Type) {
encoder.encodeString(value.name)
}
}
@Serializable
data class Surrogate(
@SerialName(typeField)