diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f2b509e7..6d8ebaa3d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## 13.0.0 +**THIS UPDATE CONTAINS BREAKING CHANGES** + +* `Core`: + * For polls, `textSources` now means `question` text sources. For `QuizPoll` there are `hint` and `hintTextSources` + for hinting + ## 12.0.1 * `Version`: diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/Edits.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/Edits.kt index f497b944cd..37988ee2bc 100644 --- a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/Edits.kt +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/Edits.kt @@ -60,7 +60,7 @@ suspend fun TelegramBot.edit( heading: Degrees? = null, proximityAlertRadius: Meters? = null, replyMarkup: InlineKeyboardMarkup? = null -) = editLiveLocation(chatId, messageId, latitude, longitude, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup) +) = editLiveLocation(chatId, messageId, latitude, longitude, livePeriod, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup) /** * @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] @@ -76,7 +76,7 @@ suspend fun TelegramBot.edit( heading: Degrees? = null, proximityAlertRadius: Meters? = null, replyMarkup: InlineKeyboardMarkup? = null -) = editLiveLocation(chat, messageId, latitude, longitude, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup) +) = editLiveLocation(chat, messageId, latitude, longitude, livePeriod, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup) /** * @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/Sends.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/Sends.kt index 75e3877744..a09a6871a8 100644 --- a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/Sends.kt +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/Sends.kt @@ -837,7 +837,8 @@ suspend inline fun TelegramBot.send( suspend fun TelegramBot.send( chatId: ChatIdentifier, question: String, - options: List, + options: List, + questionParseMode: ParseMode? = null, isAnonymous: Boolean = true, isClosed: Boolean = false, allowMultipleAnswers: Boolean = false, @@ -848,7 +849,7 @@ suspend fun TelegramBot.send( protectContent: Boolean = false, replyParameters: ReplyParameters? = null, replyMarkup: KeyboardMarkup? = null -) = sendRegularPoll(chatId, question, options, isAnonymous, isClosed, allowMultipleAnswers, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup) +) = sendRegularPoll(chatId, question, options, closeInfo, questionParseMode, isAnonymous, isClosed, allowMultipleAnswers, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup) /** * Will execute [sendRegularPoll] request @@ -860,7 +861,7 @@ suspend fun TelegramBot.send( poll: RegularPoll, isClosed: Boolean = false, question: String = poll.question, - options: List = poll.options.map { it.text }, + options: List = poll.options.map { it.asInput() }, isAnonymous: Boolean = poll.isAnonymous, allowMultipleAnswers: Boolean = poll.allowMultipleAnswers, closeInfo: ScheduledCloseInfo? = null, diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendPoll.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendPoll.kt deleted file mode 100644 index 5bce01c071..0000000000 --- a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendPoll.kt +++ /dev/null @@ -1,299 +0,0 @@ -package dev.inmo.tgbotapi.extensions.api.send.polls - -import dev.inmo.tgbotapi.bot.TelegramBot -import dev.inmo.tgbotapi.requests.send.polls.SendQuizPoll -import dev.inmo.tgbotapi.requests.send.polls.SendRegularPoll -import dev.inmo.tgbotapi.types.* -import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId -import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList -import dev.inmo.tgbotapi.types.message.ParseMode -import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup -import dev.inmo.tgbotapi.types.chat.Chat -import dev.inmo.tgbotapi.types.polls.* - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendRegularPoll( - chatId: ChatIdentifier, - question: String, - options: List, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - allowMultipleAnswers: Boolean = false, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = execute( - SendRegularPoll( - chatId, question, options, isAnonymous, isClosed, allowMultipleAnswers, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup - ) -) -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendRegularPoll( - chatId: ChatIdentifier, - poll: RegularPoll, - isClosed: Boolean = false, - question: String = poll.question, - options: List = poll.options.map { it.text }, - isAnonymous: Boolean = poll.isAnonymous, - allowMultipleAnswers: Boolean = poll.allowMultipleAnswers, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendRegularPoll(chatId, question, options, isAnonymous, isClosed, allowMultipleAnswers, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendRegularPoll( - chat: Chat, - question: String, - options: List, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - allowMultipleAnswers: Boolean = false, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chat.id.threadId, - businessConnectionId: BusinessConnectionId? = chat.id.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendRegularPoll( - chat.id, question, options, isAnonymous, isClosed, allowMultipleAnswers, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendRegularPoll( - chat: Chat, - poll: RegularPoll, - isClosed: Boolean = false, - question: String = poll.question, - options: List = poll.options.map { it.text }, - isAnonymous: Boolean = poll.isAnonymous, - allowMultipleAnswers: Boolean = poll.allowMultipleAnswers, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chat.id.threadId, - businessConnectionId: BusinessConnectionId? = chat.id.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendRegularPoll( - chat.id, question, options, isAnonymous, isClosed, allowMultipleAnswers, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendQuizPoll( - chatId: ChatIdentifier, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - explanation: String? = null, - parseMode: ParseMode? = null, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = execute( - SendQuizPoll( - chatId, question, options, correctOptionId, isAnonymous, isClosed, explanation, parseMode, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup - ) -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendQuizPoll( - chat: Chat, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - explanation: String? = null, - parseMode: ParseMode? = null, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chat.id.threadId, - businessConnectionId: BusinessConnectionId? = chat.id.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendQuizPoll( - chat.id, question, options, correctOptionId, isAnonymous, isClosed, explanation, parseMode, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendQuizPoll( - chatId: ChatIdentifier, - isClosed: Boolean = false, - quizPoll: QuizPoll, - question: String = quizPoll.question, - options: List = quizPoll.options.map { it.text }, - correctOptionId: Int = quizPoll.correctOptionId ?: error("Correct option ID must be provided by income QuizPoll or by developer"), - isAnonymous: Boolean = quizPoll.isAnonymous, - explanation: String? = null, - parseMode: ParseMode? = null, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendQuizPoll( - chatId, question, options, correctOptionId, isAnonymous, isClosed, explanation, parseMode, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend fun TelegramBot.sendQuizPoll( - chat: Chat, - isClosed: Boolean = false, - quizPoll: QuizPoll, - question: String = quizPoll.question, - options: List = quizPoll.options.map { it.text }, - correctOptionId: Int = quizPoll.correctOptionId ?: error("Correct option ID must be provided by income QuizPoll or by developer"), - isAnonymous: Boolean = quizPoll.isAnonymous, - explanation: String? = null, - parseMode: ParseMode? = null, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chat.id.threadId, - businessConnectionId: BusinessConnectionId? = chat.id.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendQuizPoll( - chat.id, question, options, correctOptionId, isAnonymous, isClosed, explanation, parseMode, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend inline fun TelegramBot.sendQuizPoll( - chatId: ChatIdentifier, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - entities: TextSourcesList, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = execute( - SendQuizPoll( - chatId, question, options, correctOptionId, isAnonymous, isClosed, entities, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup - ) -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend inline fun TelegramBot.sendQuizPoll( - chat: Chat, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - entities: TextSourcesList, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chat.id.threadId, - businessConnectionId: BusinessConnectionId? = chat.id.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendQuizPoll( - chat.id, question, options, correctOptionId, isAnonymous, isClosed, entities, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend inline fun TelegramBot.sendQuizPoll( - chatId: ChatIdentifier, - isClosed: Boolean = false, - quizPoll: QuizPoll, - question: String = quizPoll.question, - options: List = quizPoll.options.map { it.text }, - correctOptionId: Int = quizPoll.correctOptionId ?: error("Correct option ID must be provided by income QuizPoll or by developer"), - isAnonymous: Boolean = quizPoll.isAnonymous, - entities: TextSourcesList, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendQuizPoll( - chatId, question, options, correctOptionId, isAnonymous, isClosed, entities, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) - -/** - * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or - * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param - */ -suspend inline fun TelegramBot.sendQuizPoll( - chat: Chat, - isClosed: Boolean = false, - quizPoll: QuizPoll, - question: String = quizPoll.question, - options: List = quizPoll.options.map { it.text }, - correctOptionId: Int = quizPoll.correctOptionId ?: error("Correct option ID must be provided by income QuizPoll or by developer"), - isAnonymous: Boolean = quizPoll.isAnonymous, - entities: TextSourcesList, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chat.id.threadId, - businessConnectionId: BusinessConnectionId? = chat.id.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = sendQuizPoll( - chat.id, question, options, correctOptionId, isAnonymous, isClosed, entities, closeInfo, threadId, businessConnectionId, disableNotification, protectContent, replyParameters, replyMarkup -) diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendQuizPoll.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendQuizPoll.kt new file mode 100644 index 0000000000..db3e8dbf39 --- /dev/null +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendQuizPoll.kt @@ -0,0 +1,309 @@ +package dev.inmo.tgbotapi.extensions.api.send.polls + +import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.requests.send.polls.SendQuizPoll +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId +import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup +import dev.inmo.tgbotapi.types.message.ParseMode +import dev.inmo.tgbotapi.types.message.textsources.TextSource +import dev.inmo.tgbotapi.types.polls.InputPollOption +import dev.inmo.tgbotapi.types.polls.ScheduledCloseInfo + + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + questionParseMode: ParseMode? = null, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + question, + options, + correctOptionId, + questionParseMode, + explanation, + explanationParseMode, + isAnonymous, + isClosed, + openPeriod, + closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + questionEntities, + options, + correctOptionId, + explanation, + explanationParseMode, + isAnonymous, + isClosed, + openPeriod, + closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + explanationTextSources: List, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + question, + options, + correctOptionId, + explanationTextSources, + questionParseMode, + isAnonymous, + isClosed, + openPeriod, + closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + explanationTextSources: List, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + questionEntities, + options, + correctOptionId, + explanationTextSources, + isAnonymous, + isClosed, + openPeriod, + closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + closeInfo: ScheduledCloseInfo?, + questionParseMode: ParseMode? = null, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + question, + options, + correctOptionId, + closeInfo, + questionParseMode, + explanation, + explanationParseMode, + isAnonymous, + isClosed, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + closeInfo: ScheduledCloseInfo?, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + questionEntities, + options, + correctOptionId, + closeInfo, + explanation, + explanationParseMode, + isAnonymous, + isClosed, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + explanationTextSources: List, + closeInfo: ScheduledCloseInfo?, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + question, + options, + correctOptionId, + explanationTextSources, + closeInfo, + questionParseMode, + isAnonymous, + isClosed, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendQuizPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + explanationTextSources: List, + closeInfo: ScheduledCloseInfo?, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendQuizPoll( + chatId, + questionEntities, + options, + correctOptionId, + explanationTextSources, + closeInfo, + isAnonymous, + isClosed, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendRegularPoll.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendRegularPoll.kt new file mode 100644 index 0000000000..25ea41b22a --- /dev/null +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/polls/SendRegularPoll.kt @@ -0,0 +1,148 @@ +package dev.inmo.tgbotapi.extensions.api.send.polls + +import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.requests.send.polls.SendRegularPoll +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId +import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup +import dev.inmo.tgbotapi.types.message.ParseMode +import dev.inmo.tgbotapi.types.message.textsources.TextSource +import dev.inmo.tgbotapi.types.polls.InputPollOption +import dev.inmo.tgbotapi.types.polls.ScheduledCloseInfo + + +suspend fun TelegramBot.sendRegularPoll( + chatId: ChatIdentifier, + question: String, + options: List, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendRegularPoll( + chatId, + question, + options, + questionParseMode, + isAnonymous, + isClosed, + allowMultipleAnswers, + openPeriod, + closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendRegularPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendRegularPoll( + chatId, + questionEntities, + options, + isAnonymous, + isClosed, + allowMultipleAnswers, + openPeriod, + closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendRegularPoll( + chatId: ChatIdentifier, + question: String, + options: List, + closeInfo: ScheduledCloseInfo?, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendRegularPoll( + chatId, + question, + options, + closeInfo, + questionParseMode, + isAnonymous, + isClosed, + allowMultipleAnswers, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) + +suspend fun TelegramBot.sendRegularPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + closeInfo: ScheduledCloseInfo?, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = execute( + SendRegularPoll( + chatId, + questionEntities, + options, + closeInfo, + isAnonymous, + isClosed, + allowMultipleAnswers, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup + ) +) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendPoll.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendPoll.kt index eee698d32d..7ab37723d4 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendPoll.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendPoll.kt @@ -1,44 +1,39 @@ package dev.inmo.tgbotapi.requests.send.polls +import dev.inmo.tgbotapi.abstracts.TextedInput import korlibs.time.DateTime -import dev.inmo.tgbotapi.abstracts.TextedOutput import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest import dev.inmo.tgbotapi.requests.send.abstracts.SendContentMessageRequest -import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId -import dev.inmo.tgbotapi.types.message.textsources.TextSource import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup -import dev.inmo.tgbotapi.types.message.* -import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass import dev.inmo.tgbotapi.types.message.content.PollContent -import dev.inmo.tgbotapi.types.message.toRawMessageEntities +import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList import dev.inmo.tgbotapi.types.polls.* -import dev.inmo.tgbotapi.utils.extensions.makeString import korlibs.time.millisecondsLong import korlibs.time.seconds import kotlinx.serialization.* private val commonResultDeserializer: DeserializationStrategy> = TelegramBotAPIMessageDeserializationStrategyClass() -private inline val ApproximateScheduledCloseInfo.openPeriod +internal inline val ApproximateScheduledCloseInfo.openPeriod get() = openDuration.millisecondsLong.div(1000) -private inline val ExactScheduledCloseInfo.closeDate +internal inline val ExactScheduledCloseInfo.closeDate get() = closeDateTime.unixMillisLong.div(1000) -private fun checkPollInfo( +internal fun checkPollInfo( question: String, - options: List + options: List ) { 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 (it.text.length !in pollOptionTextLength) { + throw IllegalArgumentException("The length of question option text for polls must be in $pollOptionTextLength range, but was ${it.text.length}") } } if (options.size !in pollOptionsLimit) { @@ -49,7 +44,8 @@ private fun checkPollInfo( fun SendPoll( chatId: ChatIdentifier, question: String, - options: List, + options: List, + questionParseMode: ParseMode? = null, isAnonymous: Boolean = true, isClosed: Boolean = false, threadId: MessageThreadId? = chatId.threadId, @@ -62,6 +58,33 @@ fun SendPoll( chatId, question, options, + questionParseMode, + isAnonymous, + isClosed, + threadId = threadId, + businessConnectionId = businessConnectionId, + protectContent = protectContent, + disableNotification = disableNotification, + replyParameters = replyParameters, + replyMarkup = replyMarkup +) + +fun SendPoll( + chatId: ChatIdentifier, + textSources: TextSourcesList, + options: List, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendRegularPoll( + chatId, + textSources, + options, isAnonymous, isClosed, threadId = threadId, @@ -87,12 +110,12 @@ fun Poll.createRequest( ) = when (this) { is RegularPoll -> SendRegularPoll( chatId, - question, - options.map { it.text }, + textSources, + options.map { it.asInput() }, + scheduledCloseInfo, isAnonymous, isClosed, allowMultipleAnswers, - scheduledCloseInfo, threadId, businessConnectionId, disableNotification, @@ -103,13 +126,13 @@ fun Poll.createRequest( is QuizPoll -> correctOptionId ?.let { correctOptionId -> SendQuizPoll( chatId, - question, - options.map { it.text }, + textSources, + options.map { it.asInput() }, correctOptionId, + explanationTextSources, + scheduledCloseInfo, isAnonymous, isClosed, - textSources, - scheduledCloseInfo, threadId, businessConnectionId, disableNotification, @@ -119,12 +142,12 @@ fun Poll.createRequest( ) } ?: SendRegularPoll( chatId, - question, - options.map { it.text }, + textSources, + options.map { it.asInput() }, + scheduledCloseInfo, isAnonymous, isClosed, false, - scheduledCloseInfo, threadId, businessConnectionId, disableNotification, @@ -134,12 +157,12 @@ fun Poll.createRequest( ) is UnknownPollType -> SendRegularPoll( chatId, - question, - options.map { it.text }, + textSources, + options.map { it.asInput() }, + scheduledCloseInfo, isAnonymous, isClosed, false, - scheduledCloseInfo, threadId, businessConnectionId, disableNotification, @@ -149,7 +172,7 @@ fun Poll.createRequest( ) } -private fun ScheduledCloseInfo.checkSendData() { +internal fun ScheduledCloseInfo.checkSendData() { val span = when (this) { is ExactScheduledCloseInfo -> (closeDateTime - DateTime.now()).seconds is ApproximateScheduledCloseInfo -> openDuration.seconds @@ -160,9 +183,12 @@ private fun ScheduledCloseInfo.checkSendData() { } sealed class SendPoll : SendContentMessageRequest>, - ReplyingMarkupSendMessageRequest> { + ReplyingMarkupSendMessageRequest>, TextedInput { abstract val question: String - abstract val options: List + override val text: String + get() = question + abstract val questionParseMode: ParseMode? + abstract val options: List abstract val isAnonymous: Boolean abstract val isClosed: Boolean abstract val type: String @@ -187,239 +213,3 @@ sealed class SendPoll : SendContentMessageRequest>, get() = commonResultDeserializer } -@Serializable -data class SendRegularPoll( - @SerialName(chatIdField) - override val chatId: ChatIdentifier, - @SerialName(questionField) - override val question: String, - @SerialName(optionsField) - override val options: List, - @SerialName(isAnonymousField) - override val isAnonymous: Boolean = true, - @SerialName(isClosedField) - override val isClosed: Boolean = false, - @SerialName(allowsMultipleAnswersField) - val allowMultipleAnswers: Boolean = false, - @SerialName(openPeriodField) - override val openPeriod: LongSeconds?= null, - @SerialName(closeDateField) - override val closeDate: LongSeconds?, - @SerialName(messageThreadIdField) - override val threadId: MessageThreadId? = chatId.threadId, - @SerialName(businessConnectionIdField) - override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - @SerialName(disableNotificationField) - override val disableNotification: Boolean = false, - @SerialName(protectContentField) - override val protectContent: Boolean = false, - @SerialName(replyParametersField) - override val replyParameters: ReplyParameters? = null, - @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() - } -} - -fun SendRegularPoll( - chatId: ChatIdentifier, - question: String, - options: List, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - allowMultipleAnswers: Boolean = false, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = SendRegularPoll( - chatId, - question, - options, - isAnonymous, - isClosed, - allowMultipleAnswers, - (closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod, - (closeInfo as? ExactScheduledCloseInfo) ?.closeDate, - threadId, - businessConnectionId, - disableNotification, - protectContent, - replyParameters, - replyMarkup -) - -fun SendQuizPoll( - chatId: ChatIdentifier, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - explanation: String? = null, - parseMode: ParseMode? = null, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = SendQuizPoll( - chatId, - question, - options, - correctOptionId, - isAnonymous, - isClosed, - explanation, - parseMode, - null, - closeInfo, - threadId, - businessConnectionId, - disableNotification, - protectContent, - replyParameters, - replyMarkup -) - -fun SendQuizPoll( - chatId: ChatIdentifier, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - entities: List, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = SendQuizPoll( - chatId, - question, - options, - correctOptionId, - isAnonymous, - isClosed, - entities.makeString(), - null, - entities.toRawMessageEntities(), - closeInfo, - threadId, - businessConnectionId, - disableNotification, - protectContent, - replyParameters, - replyMarkup -) - -internal fun SendQuizPoll( - chatId: ChatIdentifier, - question: String, - options: List, - correctOptionId: Int, - isAnonymous: Boolean = true, - isClosed: Boolean = false, - explanation: String? = null, - parseMode: ParseMode? = null, - rawEntities: List? = null, - closeInfo: ScheduledCloseInfo? = null, - threadId: MessageThreadId? = chatId.threadId, - businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - disableNotification: Boolean = false, - protectContent: Boolean = false, - replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null -) = SendQuizPoll( - chatId, - question, - options, - correctOptionId, - isAnonymous, - isClosed, - explanation, - parseMode, - rawEntities, - (closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod, - (closeInfo as? ExactScheduledCloseInfo) ?.closeDate, - threadId, - businessConnectionId, - disableNotification, - protectContent, - replyParameters, - replyMarkup -) - -@Serializable -data class SendQuizPoll internal constructor( - @SerialName(chatIdField) - override val chatId: ChatIdentifier, - @SerialName(questionField) - override val question: String, - @SerialName(optionsField) - override val options: List, - @SerialName(correctOptionIdField) - val correctOptionId: Int, - @SerialName(isAnonymousField) - override val isAnonymous: Boolean = true, - @SerialName(isClosedField) - override val isClosed: Boolean = false, - @SerialName(explanationField) - override val text: String? = null, - @SerialName(explanationParseModeField) - override val parseMode: ParseMode? = null, - @SerialName(explanationEntitiesField) - private val rawEntities: List? = null, - @SerialName(openPeriodField) - override val openPeriod: LongSeconds? = null, - @SerialName(closeDateField) - override val closeDate: LongSeconds? = null, - @SerialName(messageThreadIdField) - override val threadId: MessageThreadId? = chatId.threadId, - @SerialName(businessConnectionIdField) - override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, - @SerialName(disableNotificationField) - override val disableNotification: Boolean = false, - @SerialName(protectContentField) - override val protectContent: Boolean = false, - @SerialName(replyParametersField) - override val replyParameters: ReplyParameters? = null, - @SerialName(replyMarkupField) - override val replyMarkup: KeyboardMarkup? = null -) : SendPoll(), TextedOutput { - override val type: String = quizPollType - override val requestSerializer: SerializationStrategy<*> - get() = serializer() - override val textSources: List? by lazy { - rawEntities ?.asTextSources(text ?: return@lazy null) - } - - init { - checkPollInfo(question, options) - closeInfo ?.checkSendData() - 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") - } - if (text != null && text.length !in explanationLimit) { - error("Quiz poll explanation size must be in range $explanationLimit," + - "but actual explanation contains ${text.length} symbols") - } - } -} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendQuizPoll.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendQuizPoll.kt new file mode 100644 index 0000000000..32d927784f --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendQuizPoll.kt @@ -0,0 +1,381 @@ +package dev.inmo.tgbotapi.requests.send.polls + +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId +import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup +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.textsources.TextSource +import dev.inmo.tgbotapi.types.message.toRawMessageEntities +import dev.inmo.tgbotapi.types.polls.ApproximateScheduledCloseInfo +import dev.inmo.tgbotapi.types.polls.ExactScheduledCloseInfo +import dev.inmo.tgbotapi.types.polls.InputPollOption +import dev.inmo.tgbotapi.types.polls.ScheduledCloseInfo +import dev.inmo.tgbotapi.utils.extensions.makeSourceString +import dev.inmo.tgbotapi.utils.extensions.makeString +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationStrategy + + +@Serializable +class SendQuizPoll internal constructor( + @SerialName(chatIdField) + override val chatId: ChatIdentifier, + @SerialName(questionField) + override val question: String, + @SerialName(optionsField) + override val options: List, + @SerialName(correctOptionIdField) + val correctOptionId: Int, + @SerialName(questionParseModeField) + override val questionParseMode: ParseMode? = null, + @SerialName(questionEntitiesField) + private val rawQuestionEntities: List = emptyList(), + @SerialName(isAnonymousField) + override val isAnonymous: Boolean = true, + @SerialName(isClosedField) + override val isClosed: Boolean = false, + @SerialName(explanationField) + val explanation: String? = null, + @SerialName(explanationParseModeField) + val explanationParseMode: ParseMode? = null, + @SerialName(explanationEntitiesField) + private val rawExplanationEntities: List? = null, + @SerialName(openPeriodField) + override val openPeriod: LongSeconds? = null, + @SerialName(closeDateField) + override val closeDate: LongSeconds? = null, + @SerialName(messageThreadIdField) + override val threadId: MessageThreadId? = chatId.threadId, + @SerialName(businessConnectionIdField) + override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + @SerialName(disableNotificationField) + override val disableNotification: Boolean = false, + @SerialName(protectContentField) + override val protectContent: Boolean = false, + @SerialName(replyParametersField) + override val replyParameters: ReplyParameters? = null, + @SerialName(replyMarkupField) + override val replyMarkup: KeyboardMarkup? = null +) : SendPoll() { + override val type: String = quizPollType + override val requestSerializer: SerializationStrategy<*> + get() = serializer() + override val textSources: List + get() = rawQuestionEntities.asTextSources(question) + val explanationTextEntities: List? by lazy { + rawExplanationEntities ?.asTextSources(text ?: return@lazy null) + } + + constructor( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + questionParseMode: ParseMode? = null, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null + ) : this( + chatId = chatId, + question = question, + options = options, + correctOptionId = correctOptionId, + questionParseMode = questionParseMode, + rawQuestionEntities = emptyList(), + isAnonymous = isAnonymous, + isClosed = isClosed, + explanation = explanation, + explanationParseMode = explanationParseMode, + rawExplanationEntities = emptyList(), + openPeriod = openPeriod, + closeDate = closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup + ) + + constructor( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null + ) : this( + chatId = chatId, + question = questionEntities.makeSourceString(), + options = options, + correctOptionId = correctOptionId, + questionParseMode = null, + rawQuestionEntities = questionEntities.toRawMessageEntities(), + isAnonymous = isAnonymous, + isClosed = isClosed, + explanation = explanation, + explanationParseMode = explanationParseMode, + rawExplanationEntities = emptyList(), + openPeriod = openPeriod, + closeDate = closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup + ) + + constructor( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + explanationTextSources: List, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null + ) : this( + chatId = chatId, + question = question, + options = options, + correctOptionId = correctOptionId, + questionParseMode = questionParseMode, + rawQuestionEntities = emptyList(), + isAnonymous = isAnonymous, + isClosed = isClosed, + explanation = explanationTextSources.makeSourceString(), + explanationParseMode = null, + rawExplanationEntities = explanationTextSources.toRawMessageEntities(), + openPeriod = openPeriod, + closeDate = closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup + ) + + constructor( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + explanationTextSources: List, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + openPeriod: LongSeconds? = null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null + ) : this( + chatId = chatId, + question = questionEntities.makeSourceString(), + options = options, + correctOptionId = correctOptionId, + questionParseMode = null, + rawQuestionEntities = questionEntities.toRawMessageEntities(), + isAnonymous = isAnonymous, + isClosed = isClosed, + explanation = explanationTextSources.makeSourceString(), + explanationParseMode = null, + rawExplanationEntities = explanationTextSources.toRawMessageEntities(), + openPeriod = openPeriod, + closeDate = closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup + ) + + init { + checkPollInfo(question, options) + closeInfo ?.checkSendData() + 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") + } + if (explanation != null && explanation.length !in explanationLimit) { + error("Quiz poll explanation size must be in range $explanationLimit," + + "but actual explanation contains ${text.length} symbols") + } + } +} + +fun SendQuizPoll( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + closeInfo: ScheduledCloseInfo?, + questionParseMode: ParseMode? = null, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendQuizPoll( + chatId = chatId, + question = question, + options = options, + correctOptionId = correctOptionId, + questionParseMode = questionParseMode, + explanation = explanation, + explanationParseMode = explanationParseMode, + isAnonymous = isAnonymous, + isClosed = isClosed, + openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, + closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup +) + +fun SendQuizPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + closeInfo: ScheduledCloseInfo?, + explanation: String? = null, + explanationParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendQuizPoll( + chatId = chatId, + questionEntities = questionEntities, + options = options, + correctOptionId = correctOptionId, + explanation = explanation, + explanationParseMode = explanationParseMode, + isAnonymous = isAnonymous, + isClosed = isClosed, + openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, + closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup +) + +fun SendQuizPoll( + chatId: ChatIdentifier, + question: String, + options: List, + correctOptionId: Int, + explanationTextSources: List, + closeInfo: ScheduledCloseInfo?, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendQuizPoll( + chatId = chatId, + question = question, + options = options, + correctOptionId = correctOptionId, + explanationTextSources = explanationTextSources, + questionParseMode = questionParseMode, + isAnonymous = isAnonymous, + isClosed = isClosed, + openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, + closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup +) + +fun SendQuizPoll( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + correctOptionId: Int, + explanationTextSources: List, + closeInfo: ScheduledCloseInfo?, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendQuizPoll( + chatId = chatId, + questionEntities = questionEntities, + options = options, + correctOptionId = correctOptionId, + explanationTextSources = explanationTextSources, + isAnonymous = isAnonymous, + isClosed = isClosed, + openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, + closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup +) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendRegularPoll.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendRegularPoll.kt new file mode 100644 index 0000000000..afd2935910 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/polls/SendRegularPoll.kt @@ -0,0 +1,231 @@ +package dev.inmo.tgbotapi.requests.send.polls + +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId +import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup +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.textsources.TextSource +import dev.inmo.tgbotapi.types.message.toRawMessageEntities +import dev.inmo.tgbotapi.types.polls.ApproximateScheduledCloseInfo +import dev.inmo.tgbotapi.types.polls.ExactScheduledCloseInfo +import dev.inmo.tgbotapi.types.polls.InputPollOption +import dev.inmo.tgbotapi.types.polls.ScheduledCloseInfo +import dev.inmo.tgbotapi.utils.EntitiesBuilder +import dev.inmo.tgbotapi.utils.EntitiesBuilderBody +import dev.inmo.tgbotapi.utils.extensions.makeSourceString +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationStrategy + +@Serializable +class SendRegularPoll private constructor( + @SerialName(chatIdField) + override val chatId: ChatIdentifier, + @SerialName(questionField) + override val question: String, + @SerialName(optionsField) + override val options: List, + @SerialName(questionParseModeField) + override val questionParseMode: ParseMode? = null, + @SerialName(questionEntitiesField) + private val rawQuestionEntities: List = emptyList(), + @SerialName(isAnonymousField) + override val isAnonymous: Boolean = true, + @SerialName(isClosedField) + override val isClosed: Boolean = false, + @SerialName(allowsMultipleAnswersField) + val allowMultipleAnswers: Boolean = false, + @SerialName(openPeriodField) + override val openPeriod: LongSeconds?= null, + @SerialName(closeDateField) + override val closeDate: LongSeconds? = null, + @SerialName(messageThreadIdField) + override val threadId: MessageThreadId? = chatId.threadId, + @SerialName(businessConnectionIdField) + override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + @SerialName(disableNotificationField) + override val disableNotification: Boolean = false, + @SerialName(protectContentField) + override val protectContent: Boolean = false, + @SerialName(replyParametersField) + override val replyParameters: ReplyParameters? = null, + @SerialName(replyMarkupField) + override val replyMarkup: KeyboardMarkup? = null +) : SendPoll() { + override val textSources: List + get() = rawQuestionEntities.asTextSources(text) + + constructor( + chatId: ChatIdentifier, + questionEntities: List, + options: List, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + openPeriod: LongSeconds?= null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null + ) : this( + chatId = chatId, + question = questionEntities.makeSourceString(), + options = options, + questionParseMode = null, + rawQuestionEntities = questionEntities.toRawMessageEntities(), + isAnonymous = isAnonymous, + isClosed = isClosed, + allowMultipleAnswers = allowMultipleAnswers, + openPeriod = openPeriod, + closeDate = closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup + ) + + constructor( + chatId: ChatIdentifier, + question: String, + options: List, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + openPeriod: LongSeconds?= null, + closeDate: LongSeconds? = null, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null + ) : this( + chatId = chatId, + question = question, + options = options, + questionParseMode = questionParseMode, + rawQuestionEntities = emptyList(), + isAnonymous = isAnonymous, + isClosed = isClosed, + allowMultipleAnswers = allowMultipleAnswers, + openPeriod = openPeriod, + closeDate = closeDate, + threadId = threadId, + businessConnectionId = businessConnectionId, + disableNotification = disableNotification, + protectContent = protectContent, + replyParameters = replyParameters, + replyMarkup = replyMarkup + ) + + override val type: String = regularPollType + override val requestSerializer: SerializationStrategy<*> + get() = serializer() + + init { + checkPollInfo(question, options) + closeInfo ?.checkSendData() + } +} + +fun SendRegularPoll( + chatId: ChatIdentifier, + question: String, + options: List, + closeInfo: ScheduledCloseInfo?, + questionParseMode: ParseMode? = null, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendRegularPoll( + chatId, + question, + options, + questionParseMode, + isAnonymous, + isClosed, + allowMultipleAnswers, + (closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod, + (closeInfo as? ExactScheduledCloseInfo) ?.closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup +) + +fun SendRegularPoll( + chatId: ChatIdentifier, + questionTextSources: List, + options: List, + closeInfo: ScheduledCloseInfo?, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null +) = SendRegularPoll( + chatId, + questionTextSources, + options, + isAnonymous, + isClosed, + allowMultipleAnswers, + (closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod, + (closeInfo as? ExactScheduledCloseInfo) ?.closeDate, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup +) + +fun SendRegularPoll( + chatId: ChatIdentifier, + options: List, + closeInfo: ScheduledCloseInfo?, + isAnonymous: Boolean = true, + isClosed: Boolean = false, + allowMultipleAnswers: Boolean = false, + threadId: MessageThreadId? = chatId.threadId, + businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, + disableNotification: Boolean = false, + protectContent: Boolean = false, + replyParameters: ReplyParameters? = null, + replyMarkup: KeyboardMarkup? = null, + builder: EntitiesBuilderBody +) = SendRegularPoll( + chatId, + EntitiesBuilder().apply(builder).build(), + options, + closeInfo, + isAnonymous, + isClosed, + allowMultipleAnswers, + threadId, + businessConnectionId, + disableNotification, + protectContent, + replyParameters, + replyMarkup +) \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt index ac4ea8ec88..6968639b56 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt @@ -441,6 +441,8 @@ const val resultsField = "results" const val resultField = "result" const val certificateField = "certificate" const val questionField = "question" +const val questionEntitiesField = "question_entities" +const val questionParseModeField = "question_parse_mode" const val optionsField = "options" const val payField = "pay" const val permissionsField = "permissions" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/InputPollOption.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/InputPollOption.kt new file mode 100644 index 0000000000..cc94c8abc9 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/InputPollOption.kt @@ -0,0 +1,59 @@ +package dev.inmo.tgbotapi.types.polls + +import dev.inmo.micro_utils.common.Warning +import dev.inmo.tgbotapi.abstracts.TextedInput +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.textsources.TextSource +import dev.inmo.tgbotapi.types.message.toRawMessageEntities +import dev.inmo.tgbotapi.utils.EntitiesBuilder +import dev.inmo.tgbotapi.utils.EntitiesBuilderBody +import dev.inmo.tgbotapi.utils.extensions.makeSourceString +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +@Serializable(InputPollOption.Companion::class) +data class InputPollOption @Warning("This constructor is not recommended to use") constructor( + override val text: String, + val parseMode: ParseMode?, + override val textSources: List, +) : TextedInput { + constructor(text: String, parseMode: ParseMode? = null) : this(text, parseMode, emptyList()) + constructor(textSources: List) : this(textSources.makeSourceString(), null, textSources) + constructor(builderBody: EntitiesBuilderBody) : this(EntitiesBuilder().apply(builderBody).build()) + + companion object : KSerializer { + @Serializable + private data class RawPollInputOption( + val text: String, + val parseMode: ParseMode? = null, + val textSources: List = emptyList(), + ) + override val descriptor: SerialDescriptor + get() = RawPollInputOption.serializer().descriptor + + override fun deserialize(decoder: Decoder): InputPollOption { + val raw = RawPollInputOption.serializer().deserialize(decoder) + return InputPollOption( + raw.text, + raw.parseMode, + raw.textSources.asTextSources(raw.text) + ) + } + + override fun serialize(encoder: Encoder, value: InputPollOption) { + RawPollInputOption.serializer().serialize( + encoder, + RawPollInputOption( + value.text, + value.parseMode, + value.textSources.toRawMessageEntities() + ) + ) + } + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/Poll.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/Poll.kt index d43734a013..793df0595f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/Poll.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/Poll.kt @@ -49,9 +49,11 @@ val LongSeconds.asExactScheduledCloseInfo @Serializable(PollSerializer::class) @ClassCastsIncluded -sealed interface Poll : ReplyInfo.External.ContentVariant { +sealed interface Poll : ReplyInfo.External.ContentVariant, TextedInput { val id: PollId val question: String + override val text: String + get() = question val options: List val votesCount: Int val isClosed: Boolean @@ -70,6 +72,8 @@ private class RawPoll( val id: PollId, @SerialName(questionField) val question: String, + @SerialName(questionEntitiesField) + val questionEntities: List, @SerialName(optionsField) val options: List, @SerialName(totalVoterCountField) @@ -104,6 +108,8 @@ data class UnknownPollType internal constructor( override val id: PollId, @SerialName(questionField) override val question: String, + @SerialName(questionEntitiesField) + override val textSources: List = emptyList(), @SerialName(optionsField) override val options: List, @SerialName(totalVoterCountField) @@ -126,6 +132,7 @@ data class UnknownPollType internal constructor( data class RegularPoll( override val id: PollId, override val question: String, + override val textSources: List, override val options: List, override val votesCount: Int, override val isClosed: Boolean = false, @@ -138,18 +145,19 @@ data class RegularPoll( data class QuizPoll( override val id: PollId, override val question: String, + override val textSources: List = emptyList(), override val options: List, override val votesCount: Int, /** * Nullable due to documentation (https://core.telegram.org/bots/api#poll) */ val correctOptionId: Int? = null, - override val text: String? = null, - override val textSources: List = emptyList(), + val explanation: String?, + val explanationTextSources: List = emptyList(), override val isClosed: Boolean = false, override val isAnonymous: Boolean = false, override val scheduledCloseInfo: ScheduledCloseInfo? = null -) : Poll, TextedInput +) : Poll @RiskFeature object PollSerializer : KSerializer { @@ -164,6 +172,7 @@ object PollSerializer : KSerializer { quizPollType -> QuizPoll( rawPoll.id, rawPoll.question, + rawPoll.questionEntities.asTextSources(rawPoll.question), rawPoll.options, rawPoll.votesCount, rawPoll.correctOptionId, @@ -176,6 +185,7 @@ object PollSerializer : KSerializer { regularPollType -> RegularPoll( rawPoll.id, rawPoll.question, + rawPoll.questionEntities.asTextSources(rawPoll.question), rawPoll.options, rawPoll.votesCount, rawPoll.isClosed, @@ -186,6 +196,7 @@ object PollSerializer : KSerializer { else -> UnknownPollType( rawPoll.id, rawPoll.question, + rawPoll.questionEntities.asTextSources(rawPoll.question), rawPoll.options, rawPoll.votesCount, rawPoll.isClosed, @@ -201,6 +212,7 @@ object PollSerializer : KSerializer { is RegularPoll -> RawPoll( value.id, value.question, + value.textSources.toRawMessageEntities(), value.options, value.votesCount, value.isClosed, @@ -213,6 +225,7 @@ object PollSerializer : KSerializer { is QuizPoll -> RawPoll( value.id, value.question, + value.textSources.toRawMessageEntities(), value.options, value.votesCount, value.isClosed, diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollOption.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollOption.kt index b5ea4dd388..ed5550741f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollOption.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollOption.kt @@ -1,47 +1,90 @@ package dev.inmo.tgbotapi.types.polls +import dev.inmo.tgbotapi.abstracts.TextedInput +import dev.inmo.tgbotapi.types.message.RawMessageEntity +import dev.inmo.tgbotapi.types.message.asTextSources +import dev.inmo.tgbotapi.types.message.textsources.TextSource +import dev.inmo.tgbotapi.types.message.toRawMessageEntities +import dev.inmo.tgbotapi.types.textEntitiesField import dev.inmo.tgbotapi.types.textField import dev.inmo.tgbotapi.types.votesCountField +import dev.inmo.tgbotapi.utils.EntitiesBuilder +import dev.inmo.tgbotapi.utils.EntitiesBuilderBody import dev.inmo.tgbotapi.utils.RiskFeature +import dev.inmo.tgbotapi.utils.extensions.makeSourceString import kotlinx.serialization.* import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder @Serializable(PollOptionSerializer::class) -sealed class PollOption { - abstract val text: String +sealed class PollOption : TextedInput { abstract val votes: Int + abstract fun asInput(): InputPollOption + companion object { fun simple( text: String, + textSources: List, votes: Int = 0 - ) = SimplePollOption(text, votes) + ) = SimplePollOption(text, textSources, votes) + fun simple( + textSources: List, + votes: Int = 0 + ) = SimplePollOption(textSources.makeSourceString(), textSources, votes) + fun simple( + votes: Int = 0, + builder: EntitiesBuilderBody + ) = simple( + EntitiesBuilder().apply(builder).build(), + votes + ) } } -@Serializable +@Serializable(PollOptionSerializer::class) data class SimplePollOption ( @SerialName(textField) override val text: String, + @SerialName(textEntitiesField) + override val textSources: List, @SerialName(votesCountField) override val votes: Int = 0 -) : PollOption() +) : PollOption() { + override fun asInput(): InputPollOption = InputPollOption(text, null, textSources) +} @RiskFeature object PollOptionSerializer : KSerializer { - override val descriptor: SerialDescriptor = SimplePollOption.serializer().descriptor - - override fun deserialize(decoder: Decoder): PollOption = SimplePollOption.serializer().deserialize( - decoder + @Serializable + private data class RawPollOption( + @SerialName(textField) + val text: String, + @SerialName(textEntitiesField) + val textSources: List, + @SerialName(votesCountField) + val votes: Int = 0 ) + override val descriptor: SerialDescriptor = RawPollOption.serializer().descriptor + + override fun deserialize(decoder: Decoder): PollOption { + val raw = RawPollOption.serializer().deserialize( + decoder + ) + + return SimplePollOption(raw.text, raw.textSources.asTextSources(raw.text), raw.votes) + } override fun serialize(encoder: Encoder, value: PollOption) { when (value) { - is SimplePollOption -> SimplePollOption.serializer().serialize( + is SimplePollOption -> RawPollOption.serializer().serialize( encoder, - value + RawPollOption( + value.text, + value.textSources.toRawMessageEntities(), + value.votes + ) ) } }