From 08d160cfa73b497655bfdff014b489803bcd1134 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 16 May 2026 16:59:40 +0600 Subject: [PATCH] add Polls updates --- CHANGELOG.md | 14 +++ agents/HELPERS.md | 1 + .../extensions/api/send/polls/SendQuizPoll.kt | 65 ++++++++++++++ .../api/send/polls/SendRegularPoll.kt | 29 +++++- .../tgbotapi/requests/send/polls/SendPoll.kt | 45 ++++++++-- .../requests/send/polls/SendQuizPoll.kt | 77 +++++++++++++++- .../requests/send/polls/SendRegularPoll.kt | 63 +++++++++++-- .../kotlin/dev/inmo/tgbotapi/types/Common.kt | 5 +- .../tgbotapi/types/files/AnimationFile.kt | 3 +- .../inmo/tgbotapi/types/files/AudioFile.kt | 3 +- .../inmo/tgbotapi/types/files/DocumentFile.kt | 3 +- .../inmo/tgbotapi/types/files/PhotoSize.kt | 3 +- .../dev/inmo/tgbotapi/types/files/Sticker.kt | 3 +- .../inmo/tgbotapi/types/files/VideoFile.kt | 2 + .../inmo/tgbotapi/types/location/Location.kt | 3 +- .../tgbotapi/types/media/InputPollMedia.kt | 43 +++++++++ .../types/media/InputPollOptionMedia.kt | 42 +++++++++ ...MediaGroupMemberTelegramMediaSerializer.kt | 8 +- .../inmo/tgbotapi/types/media/PollMedia.kt | 87 ++++++++++++++++++ .../types/media/TelegramMediaAnimation.kt | 10 ++- .../types/media/TelegramMediaAudio.kt | 11 ++- .../types/media/TelegramMediaDocument.kt | 11 ++- .../types/media/TelegramMediaLocation.kt | 30 +++++++ .../types/media/TelegramMediaPhoto.kt | 11 ++- .../types/media/TelegramMediaSerializer.kt | 1 + .../types/media/TelegramMediaSticker.kt | 26 ++++++ .../types/media/TelegramMediaVenue.kt | 48 ++++++++++ .../types/media/TelegramMediaVideo.kt | 13 ++- .../types/media/TelegramPaidMediaPhoto.kt | 8 +- .../types/media/TelegramPaidMediaVideo.kt | 8 +- .../tgbotapi/types/polls/InputPollOption.kt | 18 ++-- .../dev/inmo/tgbotapi/types/polls/Poll.kt | 59 ++++++++++-- .../inmo/tgbotapi/types/polls/PollOption.kt | 52 ++++++++--- .../dev/inmo/tgbotapi/types/venue/Venue.kt | 3 +- .../extensions/utils/ClassCastsNew.kt | 89 +++++++++++++++++++ 35 files changed, 817 insertions(+), 80 deletions(-) create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollMedia.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollOptionMedia.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/PollMedia.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaLocation.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSticker.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVenue.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index cab2b9d9fd..0d8b01ab07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,20 @@ * Added `deleteUserMessageReaction` and `deleteActorChatMessageReaction` extensions * Added `deleteAllUserMessageReactions` and `deleteAllActorChatMessageReactions` extensions * Added `@Warning`-marked catch-all `deleteMessageReaction` and `deleteAllMessageReactions` extensions +* `Core` (Bots API support): + * Added `InputMediaSticker`, `InputMediaLocation` and `InputMediaVenue` classes + * Added `InputPollMedia` and `InputPollOptionMedia` sealed interfaces representing input media variants accepted by `sendPoll` + * Added `PollMedia` class representing media attached to polls in incoming updates + * Added `media` field to `Poll`, `PollOption` and `InputPollOption` + * Added `explanationMedia` field to `QuizPoll` + * Added `membersOnly` field to `Poll` + * Added `countryCodes` field to `Poll` + * Added `media`, `membersOnly`, `countryCodes` parameters to `SendRegularPoll` and `SendPoll` factory functions + * Added `media`, `explanationMedia`, `membersOnly`, `countryCodes` parameters to `SendQuizPoll` factory functions + * Decreased minimum allowed poll options count from 2 to 1 (`pollOptionsLimit` is now `1..12`) +* `API` (Bots API support): + * Added `media`, `membersOnly`, `countryCodes` parameters to `sendRegularPoll` extension + * Added `media`, `explanationMedia`, `membersOnly`, `countryCodes` parameters to `sendQuizPoll` extension ## 33.1.0 diff --git a/agents/HELPERS.md b/agents/HELPERS.md index 3173f2aace..611b336171 100644 --- a/agents/HELPERS.md +++ b/agents/HELPERS.md @@ -3,3 +3,4 @@ FOLLOW COMMON CODE STYLE. DO NOT COMMIT OR PUSH ANY CHANGES IF PROMPT DO NOT CON `@Warning` package is `dev.inmo.micro_utils.common.Warning`. Its signature: `Warning(val message: String)` +If you have edited some constructor or function signature - you MUST update documentation accordingly AND all calls of this constructor/function. THIS RULE WORKS RECURSIVELY \ No newline at end of file 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 index ffd81abf60..9552f52787 100644 --- 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 @@ -5,6 +5,7 @@ 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.media.InputPollMedia import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.SuggestedPostParameters import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage @@ -32,6 +33,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -61,6 +66,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionParseMode = descriptionParseMode, openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -91,6 +100,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -119,6 +132,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionParseMode = descriptionParseMode, openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -148,6 +165,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionTextSources: List? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -175,6 +196,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionTextSources = descriptionTextSources, openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -203,6 +228,10 @@ public suspend fun TelegramBot.sendQuizPoll( descriptionTextSources: List? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -227,6 +256,10 @@ public suspend fun TelegramBot.sendQuizPoll( shuffleOptions = shuffleOptions, hideResultsUntilCloses = hideResultsUntilCloses, descriptionTextSources = descriptionTextSources, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, openPeriod = openPeriod, closeDate = closeDate, threadId = threadId, @@ -259,6 +292,10 @@ public suspend fun TelegramBot.sendQuizPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -287,6 +324,10 @@ public suspend fun TelegramBot.sendQuizPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -316,6 +357,10 @@ public suspend fun TelegramBot.sendQuizPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -343,6 +388,10 @@ public suspend fun TelegramBot.sendQuizPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -371,6 +420,10 @@ public suspend fun TelegramBot.sendQuizPoll( shuffleOptions: Boolean = false, hideResultsUntilCloses: Boolean = false, descriptionTextSources: List? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -397,6 +450,10 @@ public suspend fun TelegramBot.sendQuizPoll( shuffleOptions = shuffleOptions, hideResultsUntilCloses = hideResultsUntilCloses, descriptionTextSources = descriptionTextSources, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -424,6 +481,10 @@ public suspend fun TelegramBot.sendQuizPoll( shuffleOptions: Boolean = false, hideResultsUntilCloses: Boolean = false, descriptionTextSources: List? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -449,6 +510,10 @@ public suspend fun TelegramBot.sendQuizPoll( shuffleOptions = shuffleOptions, hideResultsUntilCloses = hideResultsUntilCloses, descriptionTextSources = descriptionTextSources, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, 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 index 2083e0a8ec..5f90a4dad4 100644 --- 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 @@ -5,6 +5,7 @@ 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.media.InputPollMedia import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.SuggestedPostParameters import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage @@ -30,6 +31,9 @@ public suspend fun TelegramBot.sendRegularPoll( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -39,7 +43,7 @@ public suspend fun TelegramBot.sendRegularPoll( effectId: EffectId? = null, suggestedPostParameters: SuggestedPostParameters? = null, replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null + replyMarkup: KeyboardMarkup? = null, ): ContentMessage = execute( SendRegularPoll( chatId = chatId, @@ -57,6 +61,9 @@ public suspend fun TelegramBot.sendRegularPoll( descriptionParseMode = descriptionParseMode, openPeriod = openPeriod, closeDate = closeDate, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -85,6 +92,9 @@ public suspend fun TelegramBot.sendRegularPoll( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -98,7 +108,7 @@ public suspend fun TelegramBot.sendRegularPoll( ): ContentMessage = execute( SendRegularPoll( chatId = chatId, - questionEntities = questionEntities, + questionTextSources = questionEntities, options = options, isAnonymous = isAnonymous, isClosed = isClosed, @@ -111,6 +121,9 @@ public suspend fun TelegramBot.sendRegularPoll( descriptionParseMode = descriptionParseMode, openPeriod = openPeriod, closeDate = closeDate, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -139,6 +152,9 @@ public suspend fun TelegramBot.sendRegularPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -165,6 +181,9 @@ public suspend fun TelegramBot.sendRegularPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -192,6 +211,9 @@ public suspend fun TelegramBot.sendRegularPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -217,6 +239,9 @@ public suspend fun TelegramBot.sendRegularPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, 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 7c172f7272..6a73a39d5b 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 @@ -7,6 +7,7 @@ import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageReques import dev.inmo.tgbotapi.requests.send.abstracts.SendContentMessageRequest import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId +import dev.inmo.tgbotapi.types.media.InputPollMedia import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.SuggestedPostParameters import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup @@ -61,6 +62,7 @@ fun SendPoll( shuffleOptions: Boolean = false, allowAddingOptions: Boolean = false, hideResultsUntilCloses: Boolean = false, + allowsMultipleAnswers: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, @@ -73,7 +75,10 @@ fun SendPoll( allowPaidBroadcast: Boolean = false, suggestedPostParameters: SuggestedPostParameters? = null, replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null + replyMarkup: KeyboardMarkup? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null ) = SendRegularPoll( chatId = chatId, question = question, @@ -82,13 +87,16 @@ fun SendPoll( questionParseMode = questionParseMode, isAnonymous = isAnonymous, isClosed = isClosed, - allowsMultipleAnswers = false, + allowsMultipleAnswers = allowsMultipleAnswers, allowsRevoting = allowsRevoting, shuffleOptions = shuffleOptions, allowAddingOptions = allowAddingOptions, hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -110,6 +118,7 @@ fun SendPoll( shuffleOptions: Boolean = false, allowAddingOptions: Boolean = false, hideResultsUntilCloses: Boolean = false, + allowsMultipleAnswers: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, @@ -122,7 +131,11 @@ fun SendPoll( allowPaidBroadcast: Boolean = false, suggestedPostParameters: SuggestedPostParameters? = null, replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null + replyMarkup: KeyboardMarkup? = null, + effectId: EffectId? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null ) = SendRegularPoll( chatId = chatId, questionTextSources = textSources, @@ -130,20 +143,23 @@ fun SendPoll( closeInfo = openPeriod?.asApproximateScheduledCloseInfo ?: closeDate?.asExactScheduledCloseInfo, isAnonymous = isAnonymous, isClosed = isClosed, - allowsMultipleAnswers = false, + allowsMultipleAnswers = allowsMultipleAnswers, allowsRevoting = allowsRevoting, shuffleOptions = shuffleOptions, allowAddingOptions = allowAddingOptions, hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, disableNotification = disableNotification, protectContent = protectContent, allowPaidBroadcast = allowPaidBroadcast, - effectId = null, + effectId = effectId, suggestedPostParameters = suggestedPostParameters, replyParameters = replyParameters, replyMarkup = replyMarkup @@ -162,6 +178,9 @@ fun Poll.createRequest( protectContent: Boolean = false, allowPaidBroadcast: Boolean = false, effectId: EffectId? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, suggestedPostParameters: SuggestedPostParameters? = null, replyParameters: ReplyParameters? = null, replyMarkup: KeyboardMarkup? = null @@ -180,6 +199,9 @@ fun Poll.createRequest( disableNotification = disableNotification, protectContent = protectContent, allowPaidBroadcast = allowPaidBroadcast, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, effectId = effectId, suggestedPostParameters = suggestedPostParameters, replyParameters = replyParameters, @@ -201,6 +223,9 @@ fun Poll.createRequest( disableNotification = disableNotification, protectContent = protectContent, allowPaidBroadcast = allowPaidBroadcast, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, effectId = effectId, suggestedPostParameters = suggestedPostParameters, replyParameters = replyParameters, @@ -213,13 +238,16 @@ fun Poll.createRequest( closeInfo = scheduledCloseInfo, isAnonymous = isAnonymous, isClosed = isClosed, - allowsMultipleAnswers = false, + allowsMultipleAnswers = allowsMultipleAnswers, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, disableNotification = disableNotification, protectContent = protectContent, allowPaidBroadcast = allowPaidBroadcast, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, effectId = effectId, suggestedPostParameters = suggestedPostParameters, replyParameters = replyParameters, @@ -232,13 +260,16 @@ fun Poll.createRequest( closeInfo = scheduledCloseInfo, isAnonymous = isAnonymous, isClosed = isClosed, - allowsMultipleAnswers = false, + allowsMultipleAnswers = allowsMultipleAnswers, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, disableNotification = disableNotification, protectContent = protectContent, allowPaidBroadcast = allowPaidBroadcast, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, effectId = effectId, suggestedPostParameters = suggestedPostParameters, replyParameters = replyParameters, 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 index aa2d0920be..cbfbef8c53 100644 --- 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 @@ -4,6 +4,7 @@ import dev.inmo.kslog.common.w 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.media.InputPollMedia import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.SuggestedPostParameters @@ -65,6 +66,14 @@ class SendQuizPoll internal constructor( override val openPeriod: LongSeconds? = null, @SerialName(closeDateField) override val closeDate: LongSeconds? = null, + @SerialName(mediaField) + val media: InputPollMedia? = null, + @SerialName(explanationMediaField) + val explanationMedia: InputPollMedia? = null, + @SerialName(membersOnlyField) + val membersOnly: Boolean = false, + @SerialName(countryCodesField) + val countryCodes: List? = null, @OptIn(ExperimentalSerializationApi::class) @SerialName(messageThreadIdField) @EncodeDefault @@ -120,6 +129,10 @@ class SendQuizPoll internal constructor( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -151,6 +164,10 @@ class SendQuizPoll internal constructor( rawDescriptionEntities = null, openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -175,11 +192,15 @@ class SendQuizPoll internal constructor( allowsMultipleAnswers: Boolean = false, allowsRevoting: Boolean = false, shuffleOptions: Boolean = false, - hideResultsUntilCloses: Boolean = false, + hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -211,6 +232,10 @@ class SendQuizPoll internal constructor( rawDescriptionEntities = null, openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -239,6 +264,10 @@ class SendQuizPoll internal constructor( descriptionTextSources: List? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -270,6 +299,10 @@ class SendQuizPoll internal constructor( rawDescriptionEntities = descriptionTextSources?.toRawMessageEntities(), openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -297,6 +330,10 @@ class SendQuizPoll internal constructor( descriptionTextSources: List? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -328,6 +365,10 @@ class SendQuizPoll internal constructor( rawDescriptionEntities = descriptionTextSources?.toRawMessageEntities(), openPeriod = openPeriod, closeDate = closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -386,7 +427,11 @@ fun SendQuizPoll( effectId: EffectId? = null, suggestedPostParameters: SuggestedPostParameters? = null, replyParameters: ReplyParameters? = null, - replyMarkup: KeyboardMarkup? = null + replyMarkup: KeyboardMarkup? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null ) = SendQuizPoll( chatId = chatId, question = question, @@ -405,6 +450,10 @@ fun SendQuizPoll( descriptionParseMode = descriptionParseMode, openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -433,6 +482,10 @@ fun SendQuizPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -460,6 +513,10 @@ fun SendQuizPoll( descriptionParseMode = descriptionParseMode, openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -487,6 +544,10 @@ fun SendQuizPoll( shuffleOptions: Boolean = false, hideResultsUntilCloses: Boolean = false, descriptionTextSources: List? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -513,6 +574,10 @@ fun SendQuizPoll( descriptionTextSources = descriptionTextSources, openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -539,6 +604,10 @@ fun SendQuizPoll( shuffleOptions: Boolean = false, hideResultsUntilCloses: Boolean = false, descriptionTextSources: List? = null, + media: InputPollMedia? = null, + explanationMedia: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -564,6 +633,10 @@ fun SendQuizPoll( descriptionTextSources = descriptionTextSources, openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, + media = media, + explanationMedia = explanationMedia, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, 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 index 268ba87a9d..b6d78c59fb 100644 --- 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 @@ -4,6 +4,7 @@ import dev.inmo.kslog.common.w 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.media.InputPollMedia import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.SuggestedPostParameters @@ -60,6 +61,12 @@ class SendRegularPoll constructor( override val openPeriod: LongSeconds? = null, @SerialName(closeDateField) override val closeDate: LongSeconds? = null, + @SerialName(mediaField) + val media: InputPollMedia? = null, + @SerialName(membersOnlyField) + val membersOnly: Boolean = false, + @SerialName(countryCodesField) + val countryCodes: List? = null, @OptIn(ExperimentalSerializationApi::class) @SerialName(messageThreadIdField) @EncodeDefault @@ -93,7 +100,7 @@ class SendRegularPoll constructor( constructor( chatId: ChatIdentifier, - questionEntities: List, + questionTextSources: List, options: List, isAnonymous: Boolean = true, isClosed: Boolean = false, @@ -106,6 +113,9 @@ class SendRegularPoll constructor( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -118,10 +128,10 @@ class SendRegularPoll constructor( replyMarkup: KeyboardMarkup? = null ) : this( chatId = chatId, - question = questionEntities.makeSourceString(), + question = questionTextSources.makeSourceString(), options = options, questionParseMode = null, - rawQuestionEntities = questionEntities.toRawMessageEntities(), + rawQuestionEntities = questionTextSources.toRawMessageEntities(), isAnonymous = isAnonymous, isClosed = isClosed, allowsMultipleAnswers = allowsMultipleAnswers, @@ -134,6 +144,9 @@ class SendRegularPoll constructor( rawDescriptionEntities = null, openPeriod = openPeriod, closeDate = closeDate, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, @@ -162,6 +175,9 @@ class SendRegularPoll constructor( descriptionParseMode: ParseMode? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -187,6 +203,9 @@ class SendRegularPoll constructor( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, rawDescriptionEntities = null, openPeriod = openPeriod, closeDate = closeDate, @@ -217,6 +236,9 @@ class SendRegularPoll constructor( descriptionTextSources: List? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -242,6 +264,9 @@ class SendRegularPoll constructor( hideResultsUntilCloses = hideResultsUntilCloses, description = descriptionTextSources?.makeSourceString(), descriptionParseMode = null, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, rawDescriptionEntities = descriptionTextSources?.toRawMessageEntities(), openPeriod = openPeriod, closeDate = closeDate, @@ -259,7 +284,7 @@ class SendRegularPoll constructor( constructor( chatId: ChatIdentifier, - questionEntities: List, + questionTextSources: List, options: List, isAnonymous: Boolean = true, isClosed: Boolean = false, @@ -271,6 +296,9 @@ class SendRegularPoll constructor( descriptionTextSources: List? = null, openPeriod: LongSeconds? = null, closeDate: LongSeconds? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -283,10 +311,10 @@ class SendRegularPoll constructor( replyMarkup: KeyboardMarkup? = null ) : this( chatId = chatId, - question = questionEntities.makeSourceString(), + question = questionTextSources.makeSourceString(), options = options, questionParseMode = null, - rawQuestionEntities = questionEntities.toRawMessageEntities(), + rawQuestionEntities = questionTextSources.toRawMessageEntities(), isAnonymous = isAnonymous, isClosed = isClosed, allowsMultipleAnswers = allowsMultipleAnswers, @@ -296,6 +324,9 @@ class SendRegularPoll constructor( hideResultsUntilCloses = hideResultsUntilCloses, description = descriptionTextSources?.makeSourceString(), descriptionParseMode = null, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, rawDescriptionEntities = descriptionTextSources?.toRawMessageEntities(), openPeriod = openPeriod, closeDate = closeDate, @@ -340,6 +371,9 @@ fun SendRegularPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -364,6 +398,9 @@ fun SendRegularPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, threadId = threadId, @@ -392,6 +429,9 @@ fun SendRegularPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -404,7 +444,7 @@ fun SendRegularPoll( replyMarkup: KeyboardMarkup? = null ) = SendRegularPoll( chatId = chatId, - questionEntities = questionTextSources, + questionTextSources = questionTextSources, options = options, isAnonymous = isAnonymous, isClosed = isClosed, @@ -415,6 +455,9 @@ fun SendRegularPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, openPeriod = (closeInfo as? ApproximateScheduledCloseInfo)?.openPeriod, closeDate = (closeInfo as? ExactScheduledCloseInfo)?.closeDate, threadId = threadId, @@ -442,6 +485,9 @@ fun SendRegularPoll( hideResultsUntilCloses: Boolean = false, description: String? = null, descriptionParseMode: ParseMode? = null, + media: InputPollMedia? = null, + membersOnly: Boolean = false, + countryCodes: List? = null, threadId: MessageThreadId? = chatId.threadId, directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId, businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId, @@ -467,6 +513,9 @@ fun SendRegularPoll( hideResultsUntilCloses = hideResultsUntilCloses, description = description, descriptionParseMode = descriptionParseMode, + media = media, + membersOnly = membersOnly, + countryCodes = countryCodes, threadId = threadId, directMessageThreadId = directMessageThreadId, businessConnectionId = businessConnectionId, 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 54ed22c973..52f6bfeda3 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 @@ -78,7 +78,7 @@ val invoicePayloadBytesLimit = 1 until 128 val pollOptionTextLength = 1 .. 100 val pollQuestionTextLength = 1 .. 300 -val pollOptionsLimit = 2 .. 12 +val pollOptionsLimit = 1 .. 12 val livePeriodLimit = 60 .. LiveLocation.INDEFINITE_LIVE_PERIOD @@ -292,6 +292,8 @@ const val allowsRevotingField = "allows_revoting" const val shuffleOptionsField = "shuffle_options" const val allowAddingOptionsField = "allow_adding_options" const val hideResultsUntilClosesField = "hide_results_until_closes" +const val membersOnlyField = "members_only" +const val explanationMediaField = "explanation_media" const val isAnonymousField = "is_anonymous" const val canManageTopicsField = "can_manage_topics" const val canReactToMessagesField = "can_react_to_messages" @@ -696,6 +698,7 @@ const val photoField = "photo" const val audioField = "audio" const val videoField = "video" const val animationField = "animation" +const val venueField = "venue" const val voiceField = "voice" const val videoNoteField = "video_note" const val mediaField = "media" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AnimationFile.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AnimationFile.kt index def74b6761..83ec10adbd 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AnimationFile.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AnimationFile.kt @@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.files import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.utils.MimeType import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -23,5 +24,5 @@ data class AnimationFile( override val mimeType: MimeType? = null, @SerialName(fileSizeField) override val fileSize: FileSize? = null -) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, CustomNamedMediaFile, SizedMediaFile, +) : TelegramMediaFile, PollMedia, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, CustomNamedMediaFile, SizedMediaFile, MediaContentVariant diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AudioFile.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AudioFile.kt index 422e90e771..0979d7aecb 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AudioFile.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/AudioFile.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.types.files import dev.inmo.tgbotapi.abstracts.Performerable import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.utils.MimeType import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -28,7 +29,7 @@ data class AudioFile( override val fileSize: FileSize? = null, @SerialName(thumbnailField) override val thumbnail: PhotoSize? = null -) : TelegramMediaFile, CustomNamedMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, TitledMediaFile, +) : TelegramMediaFile, PollMedia, CustomNamedMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, TitledMediaFile, Performerable, MediaContentVariant fun AudioFile.asVoiceFile() = VoiceFile( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/DocumentFile.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/DocumentFile.kt index 28d901fa93..b2e63f2669 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/DocumentFile.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/DocumentFile.kt @@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.files import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.utils.MimeType import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -20,7 +21,7 @@ data class DocumentFile( override val mimeType: MimeType? = null, @SerialName(fileNameField) override val fileName: String? = null -) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, CustomNamedMediaFile, MediaContentVariant +) : TelegramMediaFile, PollMedia, MimedMediaFile, ThumbedMediaFile, CustomNamedMediaFile, MediaContentVariant @Suppress("NOTHING_TO_INLINE") inline fun TelegramMediaFile.asDocumentFile() = if (this is DocumentFile) { diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/PhotoSize.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/PhotoSize.kt index 60f7cd7899..b64b94ea10 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/PhotoSize.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/PhotoSize.kt @@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.files import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.utils.RiskFeature import kotlinx.serialization.* import kotlin.jvm.JvmInline @@ -10,7 +11,7 @@ import kotlin.jvm.JvmInline @JvmInline value class PhotoFile( val photos: List -) : List by photos, MediaContentVariant, UsefulAsPaidMediaFile { +) : List by photos, PollMedia, MediaContentVariant, UsefulAsPaidMediaFile { val biggest: PhotoSize get() = biggest()!! override val fileId: FileId diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt index 3a0e4029bd..6c3f02657b 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/Sticker.kt @@ -5,6 +5,7 @@ package dev.inmo.tgbotapi.types.files import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.stickers.InputSticker import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.types.stickers.MaskPosition import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.nonstrictJsonFormat @@ -37,7 +38,7 @@ data class StickerSurrogate( // TODO:: Serializer @Serializable(StickerSerializer::class) -sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile, MediaContentVariant { +sealed interface Sticker : TelegramMediaFile, PollMedia, SizedMediaFile, ThumbedMediaFile, MediaContentVariant { val emoji: String? val stickerSetName: StickerSetName? val stickerFormat: StickerFormat diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/VideoFile.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/VideoFile.kt index e7705ccba0..004b00aad0 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/VideoFile.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/VideoFile.kt @@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.files import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.types.media.TelegramMediaVideo import dev.inmo.tgbotapi.types.media.TelegramPaidMediaVideo import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList @@ -38,6 +39,7 @@ data class VideoFile( @SerialName(fileSizeField) override val fileSize: FileSize? = null ) : TelegramMediaFile, + PollMedia, CustomNamedMediaFile, MimedMediaFile, CoveredMediaFile, diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt index 3de8addb9f..495b8e8892 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.types.location import dev.inmo.tgbotapi.abstracts.* import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import kotlinx.serialization.* import kotlinx.serialization.descriptors.SerialDescriptor @@ -30,7 +31,7 @@ data class StaticLocation( override val latitude: Double, @SerialName(horizontalAccuracyField) override val horizontalAccuracy: Meters? = null -) : Location +) : PollMedia, Location @Serializable data class LiveLocation( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollMedia.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollMedia.kt new file mode 100644 index 0000000000..04fc2e37aa --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollMedia.kt @@ -0,0 +1,43 @@ +package dev.inmo.tgbotapi.types.media + +import dev.inmo.tgbotapi.utils.RiskFeature +import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PolymorphicKind +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +@Serializable(InputPollMediaSerializer::class) +@ClassCastsIncluded +sealed interface InputPollMedia { + val type: String +} + +@OptIn(ExperimentalSerializationApi::class) +@RiskFeature +object InputPollMediaSerializer : KSerializer { + @OptIn(InternalSerializationApi::class) + override val descriptor: SerialDescriptor = buildSerialDescriptor(InputPollMedia::class.toString(), PolymorphicKind.OPEN) + + override fun serialize(encoder: Encoder, value: InputPollMedia) { + when (value) { + is TelegramMediaAnimation -> TelegramMediaAnimation.serializer().serialize(encoder, value) + is TelegramMediaAudio -> TelegramMediaAudio.serializer().serialize(encoder, value) + is TelegramMediaDocument -> TelegramMediaDocument.serializer().serialize(encoder, value) + // TODO::ADD TelegramMediaLivePhoto + is TelegramMediaLocation -> TelegramMediaLocation.serializer().serialize(encoder, value) + is TelegramMediaPhoto -> TelegramMediaPhoto.serializer().serialize(encoder, value) + is TelegramMediaVenue -> TelegramMediaVenue.serializer().serialize(encoder, value) + is TelegramMediaVideo -> TelegramMediaVideo.serializer().serialize(encoder, value) + } + } + + override fun deserialize(decoder: Decoder): InputPollMedia { + throw IllegalStateException("InputPollMedia can't be deserialized") + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollOptionMedia.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollOptionMedia.kt new file mode 100644 index 0000000000..d13e5a316d --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/InputPollOptionMedia.kt @@ -0,0 +1,42 @@ +package dev.inmo.tgbotapi.types.media + +import dev.inmo.tgbotapi.utils.RiskFeature +import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PolymorphicKind +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +@Serializable(InputPollOptionMediaSerializer::class) +@ClassCastsIncluded +sealed interface InputPollOptionMedia { + val type: String +} + +@OptIn(ExperimentalSerializationApi::class) +@RiskFeature +object InputPollOptionMediaSerializer : KSerializer { + @OptIn(InternalSerializationApi::class) + override val descriptor: SerialDescriptor = buildSerialDescriptor(InputPollOptionMedia::class.toString(), PolymorphicKind.OPEN) + + override fun serialize(encoder: Encoder, value: InputPollOptionMedia) { + when (value) { + is TelegramMediaAnimation -> TelegramMediaAnimation.serializer().serialize(encoder, value) + // TODO::Add TelegramMediaLivePhoto + is TelegramMediaLocation -> TelegramMediaLocation.serializer().serialize(encoder, value) + is TelegramMediaPhoto -> TelegramMediaPhoto.serializer().serialize(encoder, value) + is TelegramMediaSticker -> TelegramMediaSticker.serializer().serialize(encoder, value) + is TelegramMediaVenue -> TelegramMediaVenue.serializer().serialize(encoder, value) + is TelegramMediaVideo -> TelegramMediaVideo.serializer().serialize(encoder, value) + } + } + + override fun deserialize(decoder: Decoder): InputPollOptionMedia { + throw IllegalStateException("InputPollOptionMedia can't be deserialized") + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/MediaGroupMemberTelegramMediaSerializer.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/MediaGroupMemberTelegramMediaSerializer.kt index 7413f60c73..ed7cd7197d 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/MediaGroupMemberTelegramMediaSerializer.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/MediaGroupMemberTelegramMediaSerializer.kt @@ -28,10 +28,10 @@ object MediaGroupMemberTelegramMediaSerializer : KSerializer nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaPhoto.serializer(), json) - videoTelegramMediaType -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaVideo.serializer(), json) - audioTelegramMediaType -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaAudio.serializer(), json) - documentTelegramMediaType -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaDocument.serializer(), json) + TelegramMediaPhoto.TYPE -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaPhoto.serializer(), json) + TelegramMediaVideo.TYPE -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaVideo.serializer(), json) + TelegramMediaAudio.TYPE -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaAudio.serializer(), json) + TelegramMediaDocument.TYPE -> nonstrictJsonFormat.decodeFromJsonElement(TelegramMediaDocument.serializer(), json) else -> error("Illegal type of incoming MediaGroupMemberTelegramMedia") } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/PollMedia.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/PollMedia.kt new file mode 100644 index 0000000000..a47e394cff --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/PollMedia.kt @@ -0,0 +1,87 @@ +package dev.inmo.tgbotapi.types.media + +import dev.inmo.tgbotapi.types.animationField +import dev.inmo.tgbotapi.types.audioField +import dev.inmo.tgbotapi.types.documentField +import dev.inmo.tgbotapi.types.files.AnimationFile +import dev.inmo.tgbotapi.types.files.AudioFile +import dev.inmo.tgbotapi.types.files.DocumentFile +import dev.inmo.tgbotapi.types.files.PhotoFile +import dev.inmo.tgbotapi.types.files.PhotoSize +import dev.inmo.tgbotapi.types.files.Sticker +import dev.inmo.tgbotapi.types.files.VideoFile +import dev.inmo.tgbotapi.types.location.StaticLocation +import dev.inmo.tgbotapi.types.locationField +import dev.inmo.tgbotapi.types.photoField +import dev.inmo.tgbotapi.types.stickerField +import dev.inmo.tgbotapi.types.venue.Venue +import dev.inmo.tgbotapi.types.venueField +import dev.inmo.tgbotapi.types.videoField +import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +@ClassCastsIncluded +@Serializable(PollMedia.Serializer::class) +interface PollMedia { + object Serializer : KSerializer { + @Serializable + data class Surrogate( + @SerialName(animationField) + val animation: AnimationFile? = null, + @SerialName(audioField) + val audio: AudioFile? = null, + @SerialName(documentField) + val document: DocumentFile? = null, + @SerialName(photoField) + val photo: PhotoFile? = null, + @SerialName(stickerField) + val sticker: Sticker? = null, + @SerialName(videoField) + val video: VideoFile? = null, + @SerialName(locationField) + val location: StaticLocation? = null, + @SerialName(venueField) + val venue: Venue? = null + ) { + } + + override val descriptor: SerialDescriptor + get() = Surrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): PollMedia { + val surrogate = decoder.decodeSerializableValue(Surrogate.serializer()) + + return when { + surrogate.animation != null -> surrogate.animation + surrogate.audio != null -> surrogate.audio + surrogate.document != null -> surrogate.document + surrogate.photo != null -> surrogate.photo + surrogate.sticker != null -> surrogate.sticker + surrogate.video != null -> surrogate.video + surrogate.location != null -> surrogate.location + surrogate.venue != null -> surrogate.venue + else -> error("Unexpected media type in PollMedia deserialization") + } + } + + override fun serialize(encoder: Encoder, value: PollMedia) { + val surrogate = Surrogate( + animation = value as? AnimationFile, + audio = value as? AudioFile, + document = value as? DocumentFile, + photo = value as? PhotoFile, + sticker = value as? Sticker, + video = value as? VideoFile, + location = value as? StaticLocation, + venue = value as? Venue ?: error("Unexpected media type in PollMedia serialization") + ) + + encoder.encodeSerializableValue(Surrogate.serializer(), surrogate) + } + } +} \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAnimation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAnimation.kt index 35cce18c58..183043d609 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAnimation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAnimation.kt @@ -11,6 +11,7 @@ import dev.inmo.tgbotapi.types.message.* import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.utils.extensions.makeString +import kotlinx.serialization.EncodeDefault import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -66,8 +67,9 @@ data class TelegramMediaAnimation internal constructor( override val height: Int? = null, override val duration: Long? = null, override val thumb: InputFile? = null -) : TelegramFreeMedia, SizedTelegramMedia, DuratedTelegramMedia, ThumbedTelegramMedia, TextedOutput, SpoilerableTelegramMedia, WithCustomizableCaptionTelegramMedia { - override val type: String = "animation" +) : TelegramFreeMedia, SizedTelegramMedia, DuratedTelegramMedia, ThumbedTelegramMedia, TextedOutput, SpoilerableTelegramMedia, WithCustomizableCaptionTelegramMedia, InputPollMedia, InputPollOptionMedia { + @EncodeDefault + override val type: String = TYPE override val textSources: TextSourcesList? by lazy { rawEntities ?.asTextSources(text ?: return@lazy null) } @@ -75,4 +77,8 @@ data class TelegramMediaAnimation internal constructor( @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "animation" + } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAudio.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAudio.kt index bb753a54e0..775e7bf8f0 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAudio.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaAudio.kt @@ -14,8 +14,6 @@ import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.utils.extensions.makeString import kotlinx.serialization.* -internal const val audioTelegramMediaType = "audio" - fun TelegramMediaAudio( file: InputFile, entities: TextSourcesList, @@ -54,8 +52,9 @@ data class TelegramMediaAudio internal constructor( override val title: String? = null, override val thumb: InputFile? = null ) : TelegramFreeMedia, AudioMediaGroupMemberTelegramMedia, DuratedTelegramMedia, ThumbedTelegramMedia, TitledTelegramMedia, - Performerable { - override val type: String = audioTelegramMediaType + Performerable, InputPollMedia { + @EncodeDefault + override val type: String = TYPE override val textSources: TextSourcesList? by lazy { rawEntities ?.asTextSources(text ?: return@lazy null) } @@ -65,6 +64,10 @@ data class TelegramMediaAudio internal constructor( @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "audio" + } } fun AudioFile.toTelegramMediaAudio( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaDocument.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaDocument.kt index b7c71ebed9..57db36b309 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaDocument.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaDocument.kt @@ -12,8 +12,6 @@ import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.utils.extensions.makeString import kotlinx.serialization.* -internal const val documentTelegramMediaType = "document" - fun TelegramMediaDocument( file: InputFile, text: String? = null, @@ -59,8 +57,9 @@ data class TelegramMediaDocument internal constructor( override val thumb: InputFile? = null, @SerialName(disableContentTypeDetectionField) val disableContentTypeDetection: Boolean? = null -) : TelegramFreeMedia, DocumentMediaGroupMemberTelegramMedia, ThumbedTelegramMedia { - override val type: String = documentTelegramMediaType +) : TelegramFreeMedia, DocumentMediaGroupMemberTelegramMedia, ThumbedTelegramMedia, InputPollMedia { + @EncodeDefault + override val type: String = TYPE override val textSources: TextSourcesList? by lazy { rawEntities ?.asTextSources(text ?: return@lazy null) } @@ -70,6 +69,10 @@ data class TelegramMediaDocument internal constructor( @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "document" + } } fun DocumentFile.toTelegramMediaDocument( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaLocation.kt new file mode 100644 index 0000000000..071dfb6c2f --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaLocation.kt @@ -0,0 +1,30 @@ +package dev.inmo.tgbotapi.types.media + +import dev.inmo.tgbotapi.abstracts.HorizontallyAccured +import dev.inmo.tgbotapi.abstracts.Locationed +import dev.inmo.tgbotapi.types.Meters +import dev.inmo.tgbotapi.types.horizontalAccuracyField +import dev.inmo.tgbotapi.types.latitudeField +import dev.inmo.tgbotapi.types.longitudeField +import dev.inmo.tgbotapi.types.typeField +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class TelegramMediaLocation( + @SerialName(latitudeField) + override val latitude: Double, + @SerialName(longitudeField) + override val longitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, +) : Locationed, HorizontallyAccured, InputPollMedia, InputPollOptionMedia { + @EncodeDefault + @SerialName(typeField) + override val type: String = TYPE + + companion object { + const val TYPE = "location" + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaPhoto.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaPhoto.kt index c897a1e80c..f0feb12578 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaPhoto.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaPhoto.kt @@ -15,8 +15,6 @@ import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.utils.extensions.makeString import kotlinx.serialization.* -internal const val photoTelegramMediaType = "photo" - fun TelegramMediaPhoto( file: InputFile, text: String? = null, @@ -46,8 +44,9 @@ data class TelegramMediaPhoto internal constructor( override val spoilered: Boolean = false, @SerialName(showCaptionAboveMediaField) override val showCaptionAboveMedia: Boolean = false, -) : TelegramFreeMedia, VisualMediaGroupMemberTelegramMedia { - override val type: String = photoTelegramMediaType +) : TelegramFreeMedia, VisualMediaGroupMemberTelegramMedia, InputPollMedia, InputPollOptionMedia { + @EncodeDefault + override val type: String = TYPE override val textSources: TextSourcesList? by lazy { rawEntities ?.asTextSources(text ?: return@lazy null) } @@ -57,6 +56,10 @@ data class TelegramMediaPhoto internal constructor( @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "photo" + } } fun PhotoSize.toTelegramMediaPhoto( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSerializer.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSerializer.kt index 9975e8dedc..ce1050cc1e 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSerializer.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSerializer.kt @@ -22,6 +22,7 @@ object TelegramMediaSerializer : KSerializer { is TelegramMediaDocument -> TelegramMediaDocument.serializer().serialize(encoder, value) is TelegramPaidMediaVideo -> TelegramPaidMediaVideo.serializer().serialize(encoder, value) is TelegramPaidMediaPhoto -> TelegramPaidMediaPhoto.serializer().serialize(encoder, value) + is TelegramMediaSticker -> TelegramMediaSticker.serializer().serialize(encoder, value) } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSticker.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSticker.kt new file mode 100644 index 0000000000..613c1938b2 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaSticker.kt @@ -0,0 +1,26 @@ +package dev.inmo.tgbotapi.types.media + +import dev.inmo.tgbotapi.requests.abstracts.InputFile +import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend +import dev.inmo.tgbotapi.types.mediaField +import dev.inmo.tgbotapi.types.typeField +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class TelegramMediaSticker( + override val file: InputFile, +) : TelegramMedia, InputPollOptionMedia { + @EncodeDefault + @SerialName(typeField) + override val type: String = TYPE + + @SerialName(mediaField) + override val media: String + init { media = file.fileIdToSend } + + companion object { + const val TYPE = "sticker" + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVenue.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVenue.kt new file mode 100644 index 0000000000..8f88d894d8 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVenue.kt @@ -0,0 +1,48 @@ +package dev.inmo.tgbotapi.types.media + +import dev.inmo.tgbotapi.abstracts.CommonVenueData +import dev.inmo.tgbotapi.abstracts.Locationed +import dev.inmo.tgbotapi.types.FoursquareId +import dev.inmo.tgbotapi.types.FoursquareType +import dev.inmo.tgbotapi.types.GooglePlaceId +import dev.inmo.tgbotapi.types.GooglePlaceType +import dev.inmo.tgbotapi.types.addressField +import dev.inmo.tgbotapi.types.foursquareIdField +import dev.inmo.tgbotapi.types.foursquareTypeField +import dev.inmo.tgbotapi.types.googlePlaceIdField +import dev.inmo.tgbotapi.types.googlePlaceTypeField +import dev.inmo.tgbotapi.types.latitudeField +import dev.inmo.tgbotapi.types.longitudeField +import dev.inmo.tgbotapi.types.titleField +import dev.inmo.tgbotapi.types.typeField +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class TelegramMediaVenue( + @SerialName(latitudeField) + override val latitude: Double, + @SerialName(longitudeField) + override val longitude: Double, + @SerialName(titleField) + override val title: String, + @SerialName(addressField) + override val address: String, + @SerialName(foursquareIdField) + override val foursquareId: FoursquareId? = null, + @SerialName(foursquareTypeField) + override val foursquareType: FoursquareType? = null, + @SerialName(googlePlaceIdField) + override val googlePlaceId: GooglePlaceId? = null, + @SerialName(googlePlaceTypeField) + override val googlePlaceType: GooglePlaceType? = null +) : CommonVenueData, Locationed, InputPollMedia, InputPollOptionMedia { + @EncodeDefault + @SerialName(typeField) + override val type: String = TYPE + + companion object { + const val TYPE = "venue" + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVideo.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVideo.kt index 5e4d59e34e..c60f5731c8 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVideo.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramMediaVideo.kt @@ -14,8 +14,6 @@ import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.utils.extensions.makeString import kotlinx.serialization.* -internal const val videoTelegramMediaType = "video" - fun TelegramMediaVideo( file: InputFile, text: String? = null, @@ -100,8 +98,11 @@ data class TelegramMediaVideo internal constructor ( CoveredTelegramMedia, WithCustomStartTelegramMedia, OptionallyStreamable, - VisualMediaGroupMemberTelegramMedia { - override val type: String = videoTelegramMediaType + VisualMediaGroupMemberTelegramMedia, + InputPollMedia, + InputPollOptionMedia { + @EncodeDefault + override val type: String = TYPE override val textSources: TextSourcesList? by lazy { rawEntities ?.asTextSources(text ?: return@lazy null) } @@ -111,4 +112,8 @@ data class TelegramMediaVideo internal constructor ( @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "video" + } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaPhoto.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaPhoto.kt index f35707e8ac..39b9943b37 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaPhoto.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaPhoto.kt @@ -13,17 +13,19 @@ import dev.inmo.tgbotapi.types.message.toRawMessageEntities import dev.inmo.tgbotapi.utils.extensions.makeString import kotlinx.serialization.* -internal const val photoTelegramPaidMediaType = "photo" - @Serializable data class TelegramPaidMediaPhoto ( override val file: InputFile, ) : VisualTelegramPaidMedia { - override val type: String = photoTelegramPaidMediaType + override val type: String = TYPE @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "photo" + } } fun PhotoSize.toTelegramPaidMediaPhoto(): TelegramPaidMediaPhoto = TelegramPaidMediaPhoto( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaVideo.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaVideo.kt index 6821e2d914..70afdabd3a 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaVideo.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/media/TelegramPaidMediaVideo.kt @@ -7,8 +7,6 @@ import dev.inmo.tgbotapi.types.files.VideoFile import dev.inmo.tgbotapi.types.message.payments.PaidMedia import kotlinx.serialization.* -internal const val videoTelegramPaidMediaType = "video" - @Serializable data class TelegramPaidMediaVideo ( override val file: InputFile, @@ -29,11 +27,15 @@ data class TelegramPaidMediaVideo ( CoveredTelegramMedia, OptionallyStreamable, WithCustomStartTelegramMedia { - override val type: String = videoTelegramPaidMediaType + override val type: String = TYPE @SerialName(mediaField) override val media: String init { media = file.fileIdToSend } // crutch until js compiling will be fixed + + companion object { + const val TYPE = "video" + } } fun VideoFile.toTelegramPaidMediaVideo(): TelegramPaidMediaVideo = TelegramPaidMediaVideo( 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 index 1f361f868a..ca5da09ccb 100644 --- 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 @@ -2,6 +2,8 @@ package dev.inmo.tgbotapi.types.polls import dev.inmo.micro_utils.common.Warning import dev.inmo.tgbotapi.abstracts.TextedInput +import dev.inmo.tgbotapi.types.mediaField +import dev.inmo.tgbotapi.types.media.InputPollOptionMedia import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.asTextSources @@ -28,10 +30,12 @@ data class InputPollOption @Warning("This constructor is not recommended to use" val parseMode: ParseMode?, @SerialName(textEntitiesField) override val textSources: List, + @SerialName(mediaField) + val media: InputPollOptionMedia? = null, ) : 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()) + constructor(text: String, parseMode: ParseMode? = null, media: InputPollOptionMedia? = null) : this(text, parseMode, emptyList(), media) + constructor(textSources: List, media: InputPollOptionMedia? = null) : this(textSources.makeSourceString(), null, textSources, media) + constructor(media: InputPollOptionMedia? = null, builderBody: EntitiesBuilderBody) : this(EntitiesBuilder().apply(builderBody).build(), media) companion object : KSerializer { @Serializable @@ -42,6 +46,8 @@ data class InputPollOption @Warning("This constructor is not recommended to use" val parseMode: ParseMode? = null, @SerialName(textEntitiesField) val textSources: List = emptyList(), + @SerialName(mediaField) + val media: InputPollOptionMedia? = null, ) override val descriptor: SerialDescriptor get() = RawPollInputOption.serializer().descriptor @@ -51,7 +57,8 @@ data class InputPollOption @Warning("This constructor is not recommended to use" return InputPollOption( raw.text, raw.parseMode, - raw.textSources.asTextSources(raw.text) + raw.textSources.asTextSources(raw.text), + raw.media ) } @@ -61,7 +68,8 @@ data class InputPollOption @Warning("This constructor is not recommended to use" RawPollInputOption( value.text, value.parseMode, - value.textSources.toRawMessageEntities() + value.textSources.toRawMessageEntities(), + value.media ) ) } 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 2627636cc3..5bfb67cd6e 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 @@ -2,11 +2,13 @@ package dev.inmo.tgbotapi.types.polls +import dev.inmo.micro_utils.language_codes.IetfLang import korlibs.time.DateTime import korlibs.time.TimeSpan import dev.inmo.tgbotapi.abstracts.TextedInput import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.types.message.* import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.textsources.TextSource @@ -67,6 +69,9 @@ sealed interface Poll : ReplyInfo.External.ContentVariant, TextedInput { val allowsRevoting: Boolean val scheduledCloseInfo: ScheduledCloseInfo? val descriptionTextSources: List + val media: PollMedia? + val membersOnly: Boolean + val countryCodes: List? } @Serializable @@ -104,7 +109,17 @@ private class RawPoll( @SerialName(openPeriodField) val openPeriod: LongSeconds? = null, @SerialName(closeDateField) - val closeDate: LongSeconds? = null + val closeDate: LongSeconds? = null, + @SerialName(mediaField) + @Serializable(PollMedia.Serializer::class) + val media: PollMedia? = null, + @SerialName(explanationMediaField) + @Serializable(PollMedia.Serializer::class) + val explanationMedia: PollMedia? = null, + @SerialName(membersOnlyField) + val membersOnly: Boolean = false, + @SerialName(countryCodesField) + val countryCodes: List? = null ) { @Transient val scheduledCloseInfo: ScheduledCloseInfo? @@ -131,6 +146,12 @@ data class UnknownPollType internal constructor( override val allowsMultipleAnswers: Boolean = false, override val allowsRevoting: Boolean = true, override val descriptionTextSources: List = emptyList(), + @SerialName(mediaField) + override val media: PollMedia? = null, + @SerialName(membersOnlyField) + override val membersOnly: Boolean = false, + @SerialName(countryCodesField) + override val countryCodes: List? = null, @Serializable val raw: JsonElement? = null ) : Poll { @@ -155,7 +176,10 @@ data class RegularPoll( override val allowsMultipleAnswers: Boolean = false, override val allowsRevoting: Boolean = true, override val scheduledCloseInfo: ScheduledCloseInfo? = null, - override val descriptionTextSources: List = emptyList() + override val descriptionTextSources: List = emptyList(), + override val media: PollMedia? = null, + override val membersOnly: Boolean = false, + override val countryCodes: List? = null ) : Poll @Serializable(PollSerializer::class) @@ -173,7 +197,11 @@ data class QuizPoll( override val allowsMultipleAnswers: Boolean = false, override val allowsRevoting: Boolean = false, override val scheduledCloseInfo: ScheduledCloseInfo? = null, - override val descriptionTextSources: List = emptyList() + override val descriptionTextSources: List = emptyList(), + override val media: PollMedia? = null, + val explanationMedia: PollMedia? = null, + override val membersOnly: Boolean = false, + override val countryCodes: List? = null ) : Poll @RiskFeature @@ -199,7 +227,11 @@ object PollSerializer : KSerializer { allowsMultipleAnswers = rawPoll.allowsMultipleAnswers, allowsRevoting = rawPoll.allowsRevoting ?: false, scheduledCloseInfo = rawPoll.scheduledCloseInfo, - descriptionTextSources = rawPoll.description?.let { rawPoll.descriptionEntities.asTextSources(it) } ?: emptyList() + descriptionTextSources = rawPoll.description?.let { rawPoll.descriptionEntities.asTextSources(it) } ?: emptyList(), + media = rawPoll.media, + explanationMedia = rawPoll.explanationMedia, + membersOnly = rawPoll.membersOnly, + countryCodes = rawPoll.countryCodes ) regularPollType -> RegularPoll( id = rawPoll.id, @@ -212,7 +244,10 @@ object PollSerializer : KSerializer { allowsMultipleAnswers = rawPoll.allowsMultipleAnswers, allowsRevoting = rawPoll.allowsRevoting ?: true, scheduledCloseInfo = rawPoll.scheduledCloseInfo, - descriptionTextSources = rawPoll.description?.let { rawPoll.descriptionEntities.asTextSources(it) } ?: emptyList() + descriptionTextSources = rawPoll.description?.let { rawPoll.descriptionEntities.asTextSources(it) } ?: emptyList(), + media = rawPoll.media, + membersOnly = rawPoll.membersOnly, + countryCodes = rawPoll.countryCodes ) else -> UnknownPollType( id = rawPoll.id, @@ -222,6 +257,9 @@ object PollSerializer : KSerializer { textSources = rawPoll.questionEntities.asTextSources(rawPoll.question), isClosed = rawPoll.isClosed, isAnonymous = rawPoll.isAnonymous, + media = rawPoll.media, + membersOnly = rawPoll.membersOnly, + countryCodes = rawPoll.countryCodes, raw = asJson ) } @@ -244,7 +282,10 @@ object PollSerializer : KSerializer { description = value.descriptionTextSources.makeSourceString().takeIf { it.isNotEmpty() }, descriptionEntities = value.descriptionTextSources.toRawMessageEntities(), openPeriod = (closeInfo as? ApproximateScheduledCloseInfo) ?.openDuration ?.seconds ?.toLong(), - closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L) + closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L), + media = value.media, + membersOnly = value.membersOnly, + countryCodes = value.countryCodes ) is QuizPoll -> RawPoll( id = value.id, @@ -263,7 +304,11 @@ object PollSerializer : KSerializer { description = value.descriptionTextSources.makeSourceString().takeIf { it.isNotEmpty() }, descriptionEntities = value.descriptionTextSources.toRawMessageEntities(), openPeriod = (closeInfo as? ApproximateScheduledCloseInfo) ?.openDuration ?.seconds ?.toLong(), - closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L) + closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L), + media = value.media, + explanationMedia = value.explanationMedia, + membersOnly = value.membersOnly, + countryCodes = value.countryCodes ) is UnknownPollType -> { if (value.raw == null) { 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 5c0797f4f8..292b47d647 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 @@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.abstracts.TextedInput import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.chat.Chat import dev.inmo.tgbotapi.types.chat.User +import dev.inmo.tgbotapi.types.media.PollMedia import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.asTextSources import dev.inmo.tgbotapi.types.message.textsources.TextSource @@ -33,13 +34,17 @@ private data class PollOptionSurrogate( val addedByChat: Chat? = null, @Serializable(TelegramDateSerializer::class) @SerialName(additionDateField) - val additionDate: TelegramDate? = null + val additionDate: TelegramDate? = null, + @SerialName(mediaField) + @Serializable(PollMedia.Serializer::class) + val media: PollMedia? = null ) @Serializable(PollOption.Companion::class) sealed interface PollOption : TextedInput { val id: PollOptionPersistentId val votes: Int + val media: PollMedia? fun asInput(): InputPollOption @@ -53,7 +58,10 @@ sealed interface PollOption : TextedInput { @SerialName(textEntitiesField) override val textSources: List = emptyList(), @SerialName(votesCountField) - override val votes: Int = 0 + override val votes: Int = 0, + @SerialName(mediaField) + @Serializable(PollMedia.Serializer::class) + override val media: PollMedia? = null ) : PollOption { override fun asInput(): InputPollOption = InputPollOption(text, null, textSources) } @@ -77,7 +85,10 @@ sealed interface PollOption : TextedInput { val addedByUser: User, @Serializable(TelegramDateSerializer::class) @SerialName(additionDateField) - override val additionDate: TelegramDate + override val additionDate: TelegramDate, + @SerialName(mediaField) + @Serializable(PollMedia.Serializer::class) + override val media: PollMedia? = null ) : LatelyAdded { override fun asInput(): InputPollOption = InputPollOption(text, null, textSources) } @@ -97,7 +108,10 @@ sealed interface PollOption : TextedInput { val addedByChat: Chat, @Serializable(TelegramDateSerializer::class) @SerialName(additionDateField) - override val additionDate: TelegramDate + override val additionDate: TelegramDate, + @SerialName(mediaField) + @Serializable(PollMedia.Serializer::class) + override val media: PollMedia? = null ) : LatelyAdded { override fun asInput(): InputPollOption = InputPollOption(text, null, textSources) } @@ -116,7 +130,8 @@ sealed interface PollOption : TextedInput { textSources = textSources, votes = surrogate.votes, addedByUser = surrogate.addedByUser, - additionDate = surrogate.additionDate + additionDate = surrogate.additionDate, + media = surrogate.media ) surrogate.addedByChat != null && surrogate.additionDate != null -> AddedByChat( id = surrogate.id, @@ -124,7 +139,8 @@ sealed interface PollOption : TextedInput { textSources = textSources, votes = surrogate.votes, addedByChat = surrogate.addedByChat, - additionDate = surrogate.additionDate + additionDate = surrogate.additionDate, + media = surrogate.media ) else -> error("LatelyAdded poll option must have either added_by_user or added_by_chat") } @@ -140,7 +156,8 @@ sealed interface PollOption : TextedInput { textEntities = value.textSources.toRawMessageEntities(), votes = value.votes, addedByUser = value.addedByUser, - additionDate = value.additionDate + additionDate = value.additionDate, + media = value.media ) is AddedByChat -> PollOptionSurrogate( id = value.id, @@ -148,7 +165,8 @@ sealed interface PollOption : TextedInput { textEntities = value.textSources.toRawMessageEntities(), votes = value.votes, addedByChat = value.addedByChat, - additionDate = value.additionDate + additionDate = value.additionDate, + media = value.media ) } ) @@ -191,7 +209,8 @@ sealed interface PollOption : TextedInput { textSources = textSources, votes = surrogate.votes, addedByUser = surrogate.addedByUser, - additionDate = surrogate.additionDate + additionDate = surrogate.additionDate, + media = surrogate.media ) surrogate.addedByChat != null && surrogate.additionDate != null -> LatelyAdded.AddedByChat( id = surrogate.id, @@ -199,13 +218,15 @@ sealed interface PollOption : TextedInput { textSources = textSources, votes = surrogate.votes, addedByChat = surrogate.addedByChat, - additionDate = surrogate.additionDate + additionDate = surrogate.additionDate, + media = surrogate.media ) else -> Simple( id = surrogate.id, text = surrogate.text, textSources = textSources, - votes = surrogate.votes + votes = surrogate.votes, + media = surrogate.media ) } } @@ -218,7 +239,8 @@ sealed interface PollOption : TextedInput { id = value.id, text = value.text, textEntities = value.textSources.toRawMessageEntities(), - votes = value.votes + votes = value.votes, + media = value.media ) is LatelyAdded -> when (value) { is LatelyAdded.AddedByUser -> PollOptionSurrogate( @@ -227,7 +249,8 @@ sealed interface PollOption : TextedInput { textEntities = value.textSources.toRawMessageEntities(), votes = value.votes, addedByUser = value.addedByUser, - additionDate = value.additionDate + additionDate = value.additionDate, + media = value.media ) is LatelyAdded.AddedByChat -> PollOptionSurrogate( id = value.id, @@ -235,7 +258,8 @@ sealed interface PollOption : TextedInput { textEntities = value.textSources.toRawMessageEntities(), votes = value.votes, addedByChat = value.addedByChat, - additionDate = value.additionDate + additionDate = value.additionDate, + media = value.media ) } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt index 0a109e51a4..32506e1ecc 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt @@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.abstracts.CommonVenueData import dev.inmo.tgbotapi.abstracts.Locationed import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.location.StaticLocation +import dev.inmo.tgbotapi.types.media.PollMedia import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -23,4 +24,4 @@ data class Venue( override val googlePlaceId: GooglePlaceId? = null, @SerialName(googlePlaceTypeField) override val googlePlaceType: GooglePlaceType? = null -) : CommonVenueData, Locationed by location, ReplyInfo.External.ContentVariant +) : CommonVenueData, PollMedia, Locationed by location, ReplyInfo.External.ContentVariant diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt index e3950d6860..6b59d900b5 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt @@ -241,6 +241,11 @@ import dev.inmo.tgbotapi.types.media.AudioMediaGroupMemberTelegramMedia import dev.inmo.tgbotapi.types.media.CoveredTelegramMedia import dev.inmo.tgbotapi.types.media.DocumentMediaGroupMemberTelegramMedia import dev.inmo.tgbotapi.types.media.DuratedTelegramMedia +import dev.inmo.tgbotapi.types.media.TelegramMediaLocation +import dev.inmo.tgbotapi.types.media.TelegramMediaSticker +import dev.inmo.tgbotapi.types.media.TelegramMediaVenue +import dev.inmo.tgbotapi.types.media.InputPollMedia +import dev.inmo.tgbotapi.types.media.InputPollOptionMedia import dev.inmo.tgbotapi.types.media.MediaGroupMemberTelegramMedia import dev.inmo.tgbotapi.types.media.SizedTelegramMedia import dev.inmo.tgbotapi.types.media.SpoilerableTelegramMedia @@ -979,6 +984,12 @@ public inline fun TelegramMedia.spoilerableTelegramMediaOrThrow(): SpoilerableTe public inline fun TelegramMedia.ifSpoilerableTelegramMedia(block: (SpoilerableTelegramMedia) -> T): T? = spoilerableTelegramMediaOrNull() ?.let(block) +public inline fun TelegramMedia.inputMediaStickerOrNull(): TelegramMediaSticker? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaSticker + +public inline fun TelegramMedia.inputMediaStickerOrThrow(): TelegramMediaSticker = this as dev.inmo.tgbotapi.types.media.TelegramMediaSticker + +public inline fun TelegramMedia.ifInputMediaSticker(block: (TelegramMediaSticker) -> T): T? = inputMediaStickerOrNull() ?.let(block) + public inline fun TelegramMedia.coveredTelegramMediaOrNull(): CoveredTelegramMedia? = this as? dev.inmo.tgbotapi.types.media.CoveredTelegramMedia public inline fun TelegramMedia.coveredTelegramMediaOrThrow(): CoveredTelegramMedia = this as dev.inmo.tgbotapi.types.media.CoveredTelegramMedia @@ -1105,6 +1116,84 @@ public inline fun TelegramMedia.thumbedTelegramMediaOrThrow(): ThumbedTelegramMe public inline fun TelegramMedia.ifThumbedTelegramMedia(block: (ThumbedTelegramMedia) -> T): T? = thumbedTelegramMediaOrNull() ?.let(block) +public inline fun InputPollMedia.inputMediaLocationOrNull(): TelegramMediaLocation? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaLocation + +public inline fun InputPollMedia.inputMediaLocationOrThrow(): TelegramMediaLocation = this as dev.inmo.tgbotapi.types.media.TelegramMediaLocation + +public inline fun InputPollMedia.ifInputMediaLocation(block: (TelegramMediaLocation) -> T): T? = inputMediaLocationOrNull() ?.let(block) + +public inline fun InputPollMedia.telegramMediaAudioOrNull(): TelegramMediaAudio? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaAudio + +public inline fun InputPollMedia.telegramMediaAudioOrThrow(): TelegramMediaAudio = this as dev.inmo.tgbotapi.types.media.TelegramMediaAudio + +public inline fun InputPollMedia.ifTelegramMediaAudio(block: (TelegramMediaAudio) -> T): T? = telegramMediaAudioOrNull() ?.let(block) + +public inline fun InputPollMedia.telegramMediaVideoOrNull(): TelegramMediaVideo? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaVideo + +public inline fun InputPollMedia.telegramMediaVideoOrThrow(): TelegramMediaVideo = this as dev.inmo.tgbotapi.types.media.TelegramMediaVideo + +public inline fun InputPollMedia.ifTelegramMediaVideo(block: (TelegramMediaVideo) -> T): T? = telegramMediaVideoOrNull() ?.let(block) + +public inline fun InputPollMedia.telegramMediaPhotoOrNull(): TelegramMediaPhoto? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaPhoto + +public inline fun InputPollMedia.telegramMediaPhotoOrThrow(): TelegramMediaPhoto = this as dev.inmo.tgbotapi.types.media.TelegramMediaPhoto + +public inline fun InputPollMedia.ifTelegramMediaPhoto(block: (TelegramMediaPhoto) -> T): T? = telegramMediaPhotoOrNull() ?.let(block) + +public inline fun InputPollMedia.telegramMediaDocumentOrNull(): TelegramMediaDocument? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaDocument + +public inline fun InputPollMedia.telegramMediaDocumentOrThrow(): TelegramMediaDocument = this as dev.inmo.tgbotapi.types.media.TelegramMediaDocument + +public inline fun InputPollMedia.ifTelegramMediaDocument(block: (TelegramMediaDocument) -> T): T? = telegramMediaDocumentOrNull() ?.let(block) + +public inline fun InputPollMedia.telegramMediaAnimationOrNull(): TelegramMediaAnimation? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaAnimation + +public inline fun InputPollMedia.telegramMediaAnimationOrThrow(): TelegramMediaAnimation = this as dev.inmo.tgbotapi.types.media.TelegramMediaAnimation + +public inline fun InputPollMedia.ifTelegramMediaAnimation(block: (TelegramMediaAnimation) -> T): T? = telegramMediaAnimationOrNull() ?.let(block) + +public inline fun InputPollMedia.inputMediaVenueOrNull(): TelegramMediaVenue? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaVenue + +public inline fun InputPollMedia.inputMediaVenueOrThrow(): TelegramMediaVenue = this as dev.inmo.tgbotapi.types.media.TelegramMediaVenue + +public inline fun InputPollMedia.ifInputMediaVenue(block: (TelegramMediaVenue) -> T): T? = inputMediaVenueOrNull() ?.let(block) + +public inline fun InputPollOptionMedia.inputMediaStickerOrNull(): TelegramMediaSticker? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaSticker + +public inline fun InputPollOptionMedia.inputMediaStickerOrThrow(): TelegramMediaSticker = this as dev.inmo.tgbotapi.types.media.TelegramMediaSticker + +public inline fun InputPollOptionMedia.ifInputMediaSticker(block: (TelegramMediaSticker) -> T): T? = inputMediaStickerOrNull() ?.let(block) + +public inline fun InputPollOptionMedia.inputMediaLocationOrNull(): TelegramMediaLocation? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaLocation + +public inline fun InputPollOptionMedia.inputMediaLocationOrThrow(): TelegramMediaLocation = this as dev.inmo.tgbotapi.types.media.TelegramMediaLocation + +public inline fun InputPollOptionMedia.ifInputMediaLocation(block: (TelegramMediaLocation) -> T): T? = inputMediaLocationOrNull() ?.let(block) + +public inline fun InputPollOptionMedia.telegramMediaVideoOrNull(): TelegramMediaVideo? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaVideo + +public inline fun InputPollOptionMedia.telegramMediaVideoOrThrow(): TelegramMediaVideo = this as dev.inmo.tgbotapi.types.media.TelegramMediaVideo + +public inline fun InputPollOptionMedia.ifTelegramMediaVideo(block: (TelegramMediaVideo) -> T): T? = telegramMediaVideoOrNull() ?.let(block) + +public inline fun InputPollOptionMedia.telegramMediaPhotoOrNull(): TelegramMediaPhoto? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaPhoto + +public inline fun InputPollOptionMedia.telegramMediaPhotoOrThrow(): TelegramMediaPhoto = this as dev.inmo.tgbotapi.types.media.TelegramMediaPhoto + +public inline fun InputPollOptionMedia.ifTelegramMediaPhoto(block: (TelegramMediaPhoto) -> T): T? = telegramMediaPhotoOrNull() ?.let(block) + +public inline fun InputPollOptionMedia.telegramMediaAnimationOrNull(): TelegramMediaAnimation? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaAnimation + +public inline fun InputPollOptionMedia.telegramMediaAnimationOrThrow(): TelegramMediaAnimation = this as dev.inmo.tgbotapi.types.media.TelegramMediaAnimation + +public inline fun InputPollOptionMedia.ifTelegramMediaAnimation(block: (TelegramMediaAnimation) -> T): T? = telegramMediaAnimationOrNull() ?.let(block) + +public inline fun InputPollOptionMedia.inputMediaVenueOrNull(): TelegramMediaVenue? = this as? dev.inmo.tgbotapi.types.media.TelegramMediaVenue + +public inline fun InputPollOptionMedia.inputMediaVenueOrThrow(): TelegramMediaVenue = this as dev.inmo.tgbotapi.types.media.TelegramMediaVenue + +public inline fun InputPollOptionMedia.ifInputMediaVenue(block: (TelegramMediaVenue) -> T): T? = inputMediaVenueOrNull() ?.let(block) + public inline fun InlineKeyboardButton.unknownInlineKeyboardButtonOrNull(): UnknownInlineKeyboardButton? = this as? dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.UnknownInlineKeyboardButton public inline fun InlineKeyboardButton.unknownInlineKeyboardButtonOrThrow(): UnknownInlineKeyboardButton = this as dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.UnknownInlineKeyboardButton