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

preview version of inputs for tasks

This commit is contained in:
2025-07-07 14:38:39 +06:00
parent 0a01d2567e
commit e2ce9cfebf
6 changed files with 280 additions and 94 deletions

View File

@@ -27,3 +27,12 @@ interface TextedOutput : ParsableOutput, EntitiesOutput
interface TextedInput : TextedWithTextSources { interface TextedInput : TextedWithTextSources {
override val textSources: List<TextSource> override val textSources: List<TextSource>
} }
interface TitledInput : TextedInput {
val title: String
val titleTextSources: List<TextSource>
override val text: String
get() = title
override val textSources: List<TextSource>
get() = titleTextSources
}

View File

@@ -311,6 +311,7 @@ const val emojiListField = "emoji_list"
const val completedByUserField = "completed_by_user" const val completedByUserField = "completed_by_user"
const val completionDateField = "completion_date" const val completionDateField = "completion_date"
const val titleEntitiesField = "title_entities" const val titleEntitiesField = "title_entities"
const val tasksField = "tasks"
const val othersCanAddTasksField = "others_can_add_tasks" const val othersCanAddTasksField = "others_can_add_tasks"
const val othersCanMarkTasksAsDoneField = "others_can_mark_tasks_as_done" const val othersCanMarkTasksAsDoneField = "others_can_mark_tasks_as_done"

View File

@@ -1,62 +1,132 @@
package dev.inmo.tgbotapi.types.checklists package dev.inmo.tgbotapi.types.checklists
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.abstracts.TitledInput
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.asTextSources 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.textsources.TextSource
import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.types.tasksField
import dev.inmo.tgbotapi.types.titleEntitiesField
import dev.inmo.tgbotapi.types.titleField
import dev.inmo.tgbotapi.utils.extensions.makeSourceString import dev.inmo.tgbotapi.utils.extensions.makeSourceString
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
@Serializable(Checklist.Companion::class) @Serializable
data class Checklist( sealed interface Checklist : TitledInput {
val titleTextSources: List<TextSource>, val tasks: List<ChecklistTask>
val tasks: List<ChecklistTask>, val othersCanAddTasks: Boolean
val othersCanAddTasks: Boolean = false, val othersCanCompleteTasks: Boolean
val othersCanCompleteTasks: Boolean = false, @Serializable
) { data class Input @Warning("It is low level API. Do not use it without need") constructor(
val title: String by lazy { @SerialName(titleField)
titleTextSources.makeSourceString() override val title: String,
@SerialName(tasksField)
override val tasks: List<ChecklistTask.Input>,
@SerialName(parseModeField)
val parseMode: ParseMode? = null,
@SerialName(titleEntitiesField)
override val titleTextSources: List<TextSource> = emptyList(),
override val othersCanAddTasks: Boolean = false,
override val othersCanCompleteTasks: Boolean = false,
) : Checklist {
companion object : KSerializer<Input> {
@Serializable
private class RawChecklist(
val title: String,
val parseMode: ParseMode? = null,
val title_entities: List<RawMessageEntity> = emptyList(),
val tasks: List<ChecklistTask.Input>,
val others_can_add_tasks: Boolean = false,
val others_can_mark_tasks_as_done: Boolean = false,
)
override val descriptor: SerialDescriptor = RawChecklist.serializer().descriptor
override fun serialize(
encoder: Encoder,
value: Input
) {
RawChecklist.serializer().serialize(
encoder,
RawChecklist(
title = value.title,
title_entities = value.titleTextSources.toRawMessageEntities(),
tasks = value.tasks,
parseMode = value.parseMode,
others_can_add_tasks = value.othersCanAddTasks,
others_can_mark_tasks_as_done = value.othersCanCompleteTasks,
)
)
}
override fun deserialize(decoder: Decoder): Input {
val raw = RawChecklist.serializer().deserialize(decoder)
return Input(
title = raw.title,
titleTextSources = raw.title_entities.asTextSources(raw.title),
tasks = raw.tasks,
parseMode = raw.parseMode,
othersCanAddTasks = raw.others_can_add_tasks,
othersCanCompleteTasks = raw.others_can_mark_tasks_as_done
)
}
}
} }
companion object : KSerializer<Checklist> { @Serializable(Created.Companion::class)
@Serializable data class Created(
private class RawChecklist( override val titleTextSources: List<TextSource>,
val title: String, override val tasks: List<ChecklistTask.Created>,
val title_entities: List<RawMessageEntity> = emptyList(), override val othersCanAddTasks: Boolean = false,
val tasks: List<ChecklistTask>, override val othersCanCompleteTasks: Boolean = false,
val others_can_add_tasks: Boolean = false, ): Checklist {
val others_can_mark_tasks_as_done: Boolean = false, override val title: String by lazy {
) titleTextSources.makeSourceString()
override val descriptor: SerialDescriptor = RawChecklist.serializer().descriptor
override fun serialize(
encoder: Encoder,
value: Checklist
) {
RawChecklist.serializer().serialize(
encoder,
RawChecklist(
title = value.title,
title_entities = value.titleTextSources.toRawMessageEntities(),
tasks = value.tasks,
others_can_add_tasks = value.othersCanAddTasks,
others_can_mark_tasks_as_done = value.othersCanCompleteTasks,
)
)
} }
override fun deserialize(decoder: Decoder): Checklist { companion object : KSerializer<Created> {
val raw = RawChecklist.serializer().deserialize(decoder) @Serializable
return Checklist( private class RawChecklist(
titleTextSources = raw.title_entities.asTextSources(raw.title), val title: String,
tasks = raw.tasks, val title_entities: List<RawMessageEntity> = emptyList(),
othersCanAddTasks = raw.others_can_add_tasks, val tasks: List<ChecklistTask.Created>,
othersCanCompleteTasks = raw.others_can_mark_tasks_as_done val others_can_add_tasks: Boolean = false,
val others_can_mark_tasks_as_done: Boolean = false,
) )
override val descriptor: SerialDescriptor = RawChecklist.serializer().descriptor
override fun serialize(
encoder: Encoder,
value: Created
) {
RawChecklist.serializer().serialize(
encoder,
RawChecklist(
title = value.title,
title_entities = value.titleTextSources.toRawMessageEntities(),
tasks = value.tasks,
others_can_add_tasks = value.othersCanAddTasks,
others_can_mark_tasks_as_done = value.othersCanCompleteTasks,
)
)
}
override fun deserialize(decoder: Decoder): Created {
val raw = RawChecklist.serializer().deserialize(decoder)
return Created(
titleTextSources = raw.title_entities.asTextSources(raw.title),
tasks = raw.tasks,
othersCanAddTasks = raw.others_can_add_tasks,
othersCanCompleteTasks = raw.others_can_mark_tasks_as_done
)
}
} }
} }
} }

View File

@@ -1,19 +1,28 @@
package dev.inmo.tgbotapi.types.checklists package dev.inmo.tgbotapi.types.checklists
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.abstracts.TextedInput import dev.inmo.tgbotapi.abstracts.TextedInput
import dev.inmo.tgbotapi.abstracts.TitledInput
import dev.inmo.tgbotapi.types.TelegramDate import dev.inmo.tgbotapi.types.TelegramDate
import dev.inmo.tgbotapi.types.chat.PreviewUser import dev.inmo.tgbotapi.types.chat.PreviewUser
import dev.inmo.tgbotapi.types.completedByUserField import dev.inmo.tgbotapi.types.completedByUserField
import dev.inmo.tgbotapi.types.completionDateField import dev.inmo.tgbotapi.types.completionDateField
import dev.inmo.tgbotapi.types.idField import dev.inmo.tgbotapi.types.idField
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.asTextSources import dev.inmo.tgbotapi.types.message.asTextSources
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource
import dev.inmo.tgbotapi.types.message.textsources.TextSource import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.types.tasksField
import dev.inmo.tgbotapi.types.textEntitiesField import dev.inmo.tgbotapi.types.textEntitiesField
import dev.inmo.tgbotapi.types.textField import dev.inmo.tgbotapi.types.textField
import dev.inmo.tgbotapi.types.textParseModeField
import dev.inmo.tgbotapi.types.titleEntitiesField
import dev.inmo.tgbotapi.types.titleField
import dev.inmo.tgbotapi.utils.EntitiesBuilder
import dev.inmo.tgbotapi.utils.EntitiesBuilderBody
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.extensions.makeSourceString import dev.inmo.tgbotapi.utils.extensions.makeSourceString
import kotlinx.serialization.EncodeDefault import kotlinx.serialization.EncodeDefault
@@ -29,18 +38,93 @@ import kotlinx.serialization.encoding.Encoder
sealed interface ChecklistTask : TextedInput { sealed interface ChecklistTask : TextedInput {
val id: ChecklistTaskId val id: ChecklistTaskId
override val text: String override val text: String
val completedByUser: PreviewUser?
get() = null
val completionDate: TelegramDate?
get() = null
@Serializable @Serializable
data class InputChecklist @Warning("It is low level API. Do not use it without need") constructor(
@SerialName(titleField)
override val title: String,
@SerialName(tasksField)
val tasks: List<InputChecklistTask>,
@SerialName(parseModeField)
val parseMode: ParseMode? = null,
@SerialName(titleEntitiesField)
override val titleTextSources: List<TextSource> = emptyList(),
) : TitledInput
@Serializable(Input.Companion::class)
data class Input @Warning("It is low level API. Do not use it without need") constructor(
@SerialName(idField)
override val id: ChecklistTaskId,
@SerialName(textField)
override val text: String,
@SerialName(textParseModeField)
val parseMode: ParseMode? = null,
@SerialName(textEntitiesField)
override val textSources: List<TextSource> = emptyList(),
) : ChecklistTask {
constructor(id: ChecklistTaskId, text: String, parseMode: ParseMode? = null) : this(
id = id,
text = text,
parseMode = parseMode,
textSources = emptyList()
)
constructor(id: ChecklistTaskId, textSources: List<TextSource>) : this(
id = id,
text = textSources.makeSourceString(),
parseMode = null,
textSources = textSources
)
constructor(id: ChecklistTaskId, builderBody: EntitiesBuilderBody) : this(
id = id,
textSources = EntitiesBuilder().apply(builderBody).build()
)
companion object : KSerializer<Input> {
@Serializable
private data class RawInput(
@SerialName(idField)
val id: ChecklistTaskId,
@SerialName(textField)
val text: String,
@SerialName(textParseModeField)
val parseMode: ParseMode? = null,
@SerialName(textEntitiesField)
val textSources: List<RawMessageEntity> = emptyList(),
)
override val descriptor: SerialDescriptor
get() = RawInput.serializer().descriptor
override fun deserialize(decoder: Decoder): Input {
val raw = RawInput.serializer().deserialize(decoder)
return Input(
raw.id,
raw.text,
raw.parseMode,
raw.textSources.asTextSources(raw.text)
)
}
override fun serialize(encoder: Encoder, value: Input) {
RawInput.serializer().serialize(
encoder,
RawInput(
value.id,
value.text,
value.parseMode,
value.textSources.toRawMessageEntities()
)
)
}
}
}
@Serializable(Created.Serializer::class)
data class Undone( data class Undone(
@SerialName(idField) @SerialName(idField)
override val id: ChecklistTaskId, override val id: ChecklistTaskId,
@SerialName(textEntitiesField) @SerialName(textEntitiesField)
override val textSources: List<TextSource> = emptyList(), override val textSources: List<TextSource> = emptyList(),
) : ChecklistTask { ) : ChecklistTask.Created {
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@EncodeDefault @EncodeDefault
@Serializable @Serializable
@@ -55,7 +139,7 @@ sealed interface ChecklistTask : TextedInput {
) )
} }
@Serializable @Serializable(Created.Serializer::class)
data class Done( data class Done(
@SerialName(idField) @SerialName(idField)
override val id: ChecklistTaskId, override val id: ChecklistTaskId,
@@ -65,7 +149,7 @@ sealed interface ChecklistTask : TextedInput {
override val completionDate: TelegramDate, override val completionDate: TelegramDate,
@SerialName(textEntitiesField) @SerialName(textEntitiesField)
override val textSources: List<TextSource> = emptyList() override val textSources: List<TextSource> = emptyList()
) : ChecklistTask { ) : ChecklistTask.Created {
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@EncodeDefault @EncodeDefault
@Serializable @Serializable
@@ -86,55 +170,62 @@ sealed interface ChecklistTask : TextedInput {
) )
) )
} }
@RiskFeature
object Serializer : KSerializer<ChecklistTask> {
@Serializable
private data class RawChecklistTask(
@SerialName(idField)
val id: ChecklistTaskId,
@SerialName(textField)
val text: String,
@SerialName(textEntitiesField)
val textSources: List<RawMessageEntity> = emptyList(),
@SerialName(completedByUserField)
val completedByUser: PreviewUser? = null,
@SerialName(completionDateField)
val completionDate: TelegramDate = TelegramDate(0), // TelegramDate(0) is the default according to https://core.telegram.org/bots/api#checklisttask
)
override val descriptor: SerialDescriptor = RawChecklistTask.serializer().descriptor
override fun deserialize(decoder: Decoder): ChecklistTask { @Serializable(Created.Serializer::class)
val raw = RawChecklistTask.serializer().deserialize( sealed interface Created : ChecklistTask {
decoder val completedByUser: PreviewUser?
get() = null
val completionDate: TelegramDate?
get() = null
@RiskFeature
object Serializer : KSerializer<Created> {
@Serializable
private data class RawCreatedChecklistTask(
@SerialName(idField)
val id: ChecklistTaskId,
@SerialName(textField)
val text: String,
@SerialName(textEntitiesField)
val textSources: List<RawMessageEntity> = emptyList(),
@SerialName(completedByUserField)
val completedByUser: PreviewUser? = null,
@SerialName(completionDateField)
val completionDate: TelegramDate = TelegramDate(0), // TelegramDate(0) is the default according to https://core.telegram.org/bots/api#checklisttask
) )
override val descriptor: SerialDescriptor = RawCreatedChecklistTask.serializer().descriptor
return when { override fun deserialize(decoder: Decoder): Created {
raw.completedByUser != null -> Done( val raw = RawCreatedChecklistTask.serializer().deserialize(
id = raw.id, decoder
completedByUser = raw.completedByUser,
completionDate = raw.completionDate,
textSources = raw.textSources.asTextSources(raw.text),
) )
else -> Undone(
id = raw.id, return when {
textSources = raw.textSources.asTextSources(raw.text), raw.completedByUser != null -> Done(
id = raw.id,
completedByUser = raw.completedByUser,
completionDate = raw.completionDate,
textSources = raw.textSources.asTextSources(raw.text),
)
else -> Undone(
id = raw.id,
textSources = raw.textSources.asTextSources(raw.text),
)
}
}
override fun serialize(encoder: Encoder, value: Created) {
RawCreatedChecklistTask.serializer().serialize(
encoder,
RawCreatedChecklistTask(
id = value.id,
text = value.text,
completedByUser = value.completedByUser,
completionDate = value.completionDate ?: TelegramDate(0),
textSources = value.textSources.toRawMessageEntities()
)
) )
} }
} }
override fun serialize(encoder: Encoder, value: ChecklistTask) {
RawChecklistTask.serializer().serialize(
encoder,
RawChecklistTask(
id = value.id,
text = value.text,
completedByUser = value.completedByUser,
completionDate = value.completionDate ?: TelegramDate(0),
textSources = value.textSources.toRawMessageEntities()
)
)
}
} }
} }

View File

@@ -6,5 +6,5 @@ import kotlin.jvm.JvmInline
@Serializable @Serializable
@JvmInline @JvmInline
value class ChecklistTaskId( value class ChecklistTaskId(
val int: Int val int: UInt
) )

View File

@@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.types.checklists
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.abstracts.TextedInput
import dev.inmo.tgbotapi.abstracts.TitledInput
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.tasksField
import dev.inmo.tgbotapi.types.titleEntitiesField
import dev.inmo.tgbotapi.types.titleField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable