1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-06-02 07:55:25 +00:00
tgbotapi/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendPoll.kt

424 lines
13 KiB
Kotlin
Raw Normal View History

2020-10-04 11:06:30 +00:00
package dev.inmo.tgbotapi.requests.send.polls
2020-01-23 11:01:13 +00:00
2023-05-27 12:19:14 +00:00
import korlibs.time.DateTime
2022-05-01 16:13:40 +00:00
import dev.inmo.tgbotapi.abstracts.TextedOutput
2020-10-04 11:06:30 +00:00
import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
import dev.inmo.tgbotapi.types.*
2022-05-01 14:36:07 +00:00
import dev.inmo.tgbotapi.types.message.textsources.TextSource
2022-05-01 14:43:03 +00:00
import dev.inmo.tgbotapi.types.message.ParseMode
2020-10-04 11:06:30 +00:00
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
2022-05-01 14:36:07 +00:00
import dev.inmo.tgbotapi.types.message.*
import dev.inmo.tgbotapi.types.message.RawMessageEntity
2020-10-04 11:06:30 +00:00
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.PollContent
2022-05-01 14:36:07 +00:00
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
2020-10-04 11:06:30 +00:00
import dev.inmo.tgbotapi.types.polls.*
2021-08-08 12:00:42 +00:00
import dev.inmo.tgbotapi.utils.extensions.makeString
2024-01-05 07:45:30 +00:00
import korlibs.time.millisecondsLong
import korlibs.time.seconds
2020-01-23 11:01:13 +00:00
import kotlinx.serialization.*
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PollContent>> = TelegramBotAPIMessageDeserializationStrategyClass()
2021-02-06 05:53:30 +00:00
private inline val ApproximateScheduledCloseInfo.openPeriod
get() = openDuration.millisecondsLong.div(1000)
private inline val ExactScheduledCloseInfo.closeDate
get() = closeDateTime.unixMillisLong.div(1000)
2020-01-23 11:01:13 +00:00
private fun checkPollInfo(
question: String,
options: List<String>
) {
if (question.length !in pollQuestionTextLength) {
throw IllegalArgumentException("The length of questions for polls must be in $pollQuestionTextLength range, but was ${question.length}")
}
options.forEach {
if (it.length !in pollOptionTextLength) {
throw IllegalArgumentException("The length of question option text for polls must be in $pollOptionTextLength range, but was ${it.length}")
}
}
if (options.size !in pollOptionsLimit) {
throw IllegalArgumentException("The amount of question options for polls must be in $pollOptionsLimit range, but was ${options.size}")
}
}
fun SendPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
2020-01-23 11:01:13 +00:00
disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
2020-11-05 17:48:23 +00:00
allowSendingWithoutReply: Boolean? = null,
2020-01-23 11:01:13 +00:00
replyMarkup: KeyboardMarkup? = null
) = SendRegularPoll(
chatId,
question,
options,
isAnonymous,
isClosed,
2022-11-07 18:11:14 +00:00
threadId = threadId,
protectContent = protectContent,
2020-11-05 17:48:23 +00:00
allowSendingWithoutReply = allowSendingWithoutReply,
2020-01-23 11:01:13 +00:00
disableNotification = disableNotification,
replyToMessageId = replyToMessageId,
replyMarkup = replyMarkup
)
2020-01-23 14:42:54 +00:00
/**
* @return [SendPoll] in case when all is right. It can return [SendRegularPoll] for [QuizPoll] in case if
* [QuizPoll.correctOptionId] equal to null
*/
fun Poll.createRequest(
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = when (this) {
is RegularPoll -> SendRegularPoll(
chatId,
question,
options.map { it.text },
isAnonymous,
isClosed,
allowMultipleAnswers,
2020-04-24 13:08:54 +00:00
scheduledCloseInfo,
2022-11-07 18:11:14 +00:00
threadId,
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
2020-01-23 14:42:54 +00:00
is QuizPoll -> correctOptionId ?.let { correctOptionId ->
SendQuizPoll(
chatId,
question,
options.map { it.text },
correctOptionId,
isAnonymous,
isClosed,
textSources,
2020-04-24 13:08:54 +00:00
scheduledCloseInfo,
2022-11-07 18:11:14 +00:00
threadId,
2020-01-23 14:42:54 +00:00
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
2020-01-23 14:42:54 +00:00
replyToMessageId,
allowSendingWithoutReply,
2020-01-23 14:42:54 +00:00
replyMarkup
)
} ?: SendRegularPoll(
chatId,
question,
options.map { it.text },
isAnonymous,
isClosed,
2020-01-23 14:42:54 +00:00
false,
2020-04-24 13:08:54 +00:00
scheduledCloseInfo,
2022-11-07 18:11:14 +00:00
threadId,
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
is UnknownPollType -> SendRegularPoll(
chatId,
question,
options.map { it.text },
isAnonymous,
isClosed,
false,
2020-04-24 13:08:54 +00:00
scheduledCloseInfo,
2022-11-07 18:11:14 +00:00
threadId,
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
}
private fun ScheduledCloseInfo.checkSendData() {
val span = when (this) {
is ExactScheduledCloseInfo -> (closeDateTime - DateTime.now()).seconds
is ApproximateScheduledCloseInfo -> openDuration.seconds
}.toInt()
if (span !in openPeriodPollSecondsLimit) {
error("Duration of autoclose for polls must be in range $openPeriodPollSecondsLimit, but was $span")
}
}
2020-01-23 11:01:13 +00:00
sealed class SendPoll : SendMessageRequest<ContentMessage<PollContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<PollContent>> {
abstract val question: String
abstract val options: List<String>
abstract val isAnonymous: Boolean
abstract val isClosed: Boolean
abstract val type: String
2020-04-24 13:08:54 +00:00
internal abstract val openPeriod: LongSeconds?
internal abstract val closeDate: LongSeconds?
2021-02-06 05:53:30 +00:00
protected val creationDate = DateTime.now()
open val closeInfo: ScheduledCloseInfo?
get() {
val openPeriod = openPeriod
val closeDate = closeDate
return when {
openPeriod != null -> openPeriod.asApproximateScheduledCloseInfo(creationDate)
closeDate != null -> closeDate.asExactScheduledCloseInfo
else -> null
}
}
2020-01-23 11:01:13 +00:00
override fun method(): String = "sendPoll"
override val resultDeserializer: DeserializationStrategy<ContentMessage<PollContent>>
get() = commonResultDeserializer
}
@Serializable
data class SendRegularPoll(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(questionField)
override val question: String,
@SerialName(optionsField)
override val options: List<String>,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = true,
@SerialName(isClosedField)
override val isClosed: Boolean = false,
@SerialName(allowsMultipleAnswersField)
val allowMultipleAnswers: Boolean = false,
2021-02-06 05:53:30 +00:00
@SerialName(openPeriodField)
override val openPeriod: LongSeconds?= null,
@SerialName(closeDateField)
override val closeDate: LongSeconds?,
2022-11-07 18:11:14 +00:00
@SerialName(messageThreadIdField)
override val threadId: MessageThreadId? = chatId.threadId,
2020-01-23 11:01:13 +00:00
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
@SerialName(protectContentField)
override val protectContent: Boolean = false,
2020-01-23 11:01:13 +00:00
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageId? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
2020-01-23 11:01:13 +00:00
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendPoll() {
override val type: String = regularPollType
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
init {
checkPollInfo(question, options)
closeInfo ?.checkSendData()
2020-01-23 11:01:13 +00:00
}
}
2021-02-06 05:53:30 +00:00
fun SendRegularPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
allowMultipleAnswers: Boolean = false,
closeInfo: ScheduledCloseInfo? = null,
threadId: MessageThreadId? = chatId.threadId,
2021-02-06 05:53:30 +00:00
disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
2021-02-06 05:53:30 +00:00
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendRegularPoll(
chatId,
question,
options,
isAnonymous,
isClosed,
allowMultipleAnswers,
(closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod,
(closeInfo as? ExactScheduledCloseInfo) ?.closeDate,
2022-11-07 18:11:14 +00:00
threadId,
2021-02-06 05:53:30 +00:00
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
2021-02-06 05:53:30 +00:00
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
fun SendQuizPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
correctOptionId: Int,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
explanation: String? = null,
parseMode: ParseMode? = null,
closeInfo: ScheduledCloseInfo? = null,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendQuizPoll(
chatId,
question,
options,
correctOptionId,
isAnonymous,
isClosed,
explanation,
parseMode,
null,
closeInfo,
2022-11-07 18:11:14 +00:00
threadId,
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
fun SendQuizPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
correctOptionId: Int,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
2021-05-29 09:34:14 +00:00
entities: List<TextSource>,
closeInfo: ScheduledCloseInfo? = null,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendQuizPoll(
chatId,
question,
options,
correctOptionId,
isAnonymous,
isClosed,
entities.makeString(),
null,
entities.toRawMessageEntities(),
closeInfo,
2022-11-07 18:11:14 +00:00
threadId,
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
2021-02-06 05:53:30 +00:00
internal fun SendQuizPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
correctOptionId: Int,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
explanation: String? = null,
parseMode: ParseMode? = null,
rawEntities: List<RawMessageEntity>? = null,
closeInfo: ScheduledCloseInfo? = null,
threadId: MessageThreadId? = chatId.threadId,
2021-02-06 05:53:30 +00:00
disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
2021-02-06 05:53:30 +00:00
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendQuizPoll(
chatId,
question,
options,
correctOptionId,
isAnonymous,
isClosed,
explanation,
parseMode,
rawEntities,
(closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod,
(closeInfo as? ExactScheduledCloseInfo) ?.closeDate,
2022-11-07 18:11:14 +00:00
threadId,
2021-02-06 05:53:30 +00:00
disableNotification,
2022-01-01 14:13:22 +00:00
protectContent,
2021-02-06 05:53:30 +00:00
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
2020-01-23 11:01:13 +00:00
@Serializable
data class SendQuizPoll internal constructor(
2020-01-23 11:01:13 +00:00
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(questionField)
override val question: String,
@SerialName(optionsField)
override val options: List<String>,
@SerialName(correctOptionIdField)
val correctOptionId: Int,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = true,
@SerialName(isClosedField)
override val isClosed: Boolean = false,
2020-04-24 12:46:26 +00:00
@SerialName(explanationField)
2021-04-29 05:52:38 +00:00
override val text: String? = null,
2020-04-24 12:46:26 +00:00
@SerialName(explanationParseModeField)
override val parseMode: ParseMode? = null,
@SerialName(explanationEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
2021-02-06 05:53:30 +00:00
@SerialName(openPeriodField)
override val openPeriod: LongSeconds? = null,
@SerialName(closeDateField)
override val closeDate: LongSeconds? = null,
2022-11-07 18:11:14 +00:00
@SerialName(messageThreadIdField)
override val threadId: MessageThreadId? = chatId.threadId,
2020-01-23 11:01:13 +00:00
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
2022-01-01 14:13:22 +00:00
@SerialName(protectContentField)
override val protectContent: Boolean = false,
2020-01-23 11:01:13 +00:00
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageId? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
2020-01-23 11:01:13 +00:00
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
2021-05-29 08:31:44 +00:00
) : SendPoll(), TextedOutput {
2020-01-23 11:01:13 +00:00
override val type: String = quizPollType
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
2021-04-29 05:52:38 +00:00
override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
2020-01-23 11:01:13 +00:00
init {
checkPollInfo(question, options)
closeInfo ?.checkSendData()
2020-01-23 11:01:13 +00:00
val correctOptionIdRange = 0 .. options.size
if (correctOptionId !in correctOptionIdRange) {
throw IllegalArgumentException("Correct option id must be in range of $correctOptionIdRange, but actual " +
"value is $correctOptionId")
}
2021-04-29 05:52:38 +00:00
if (text != null && text.length !in explanationLimit) {
error("Quiz poll explanation size must be in range $explanationLimit," +
2021-04-29 05:52:38 +00:00
"but actual explanation contains ${text.length} symbols")
2020-04-24 12:46:26 +00:00
}
2020-01-23 11:01:13 +00:00
}
2020-02-06 16:52:10 +00:00
}