1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-26 03:58:44 +00:00

Merge pull request #362 from InsanusMokrassar/0.34.0

0.34.0
This commit is contained in:
InsanusMokrassar 2021-04-29 19:03:29 +06:00 committed by GitHub
commit b055268979
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 840 additions and 503 deletions

View File

@ -1,5 +1,30 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 0.34.0
**UPDATE UP TO Telegram Bot API 5.2**
_**ALL OLD DEPRECATIONS WERE REMOVED**_
* `Core`:
* Type `ChatType` has been added
* New `ExtendedChat` for unknown messages `UnknownExtendedChat` has been added
* `SendInvoice#startParameter` becomes optional and replaced in `SendInvoice` constructor
* New interface `CommonSendInvoiceData` has been added
* Fields `CommonSendInvoiceData#maxTipAmount` and `CommonSendInvoiceData#suggestedTipAmounts` have been added
* New type `InputInvoiceMessageContent` has been added
* New interface `TextedWithTextSources` on top of `Texted` interface
* Interface `TextedInput` now extends `TextedWithTextSources` with overriding of `textSources` field as not
nullable
* `textSources` become main field in `TextedInput`
* **MIGRATION** Remove all `import dev.inmo.tgbotapi.CommonAbstracts.textSources` in your project
* `textEntities` become are calculable property in `TextedInput`
* Interface `Captioned` and `CaptionedInput` now is deprecated
* Most of captions usages were replaced with texts
* Interface `Explained` and `ExplainedInput` now is deprecated
* Most of captions usages were replaced with texts
* Interface `VoiceChatEvent` now is `CommonEvent`
* Mechanism of `RawMessageEntity` converting were fully rewritten
## 0.33.4 ## 0.33.4
* `Common`: * `Common`:

View File

@ -17,6 +17,6 @@ micro_utils_version=0.4.35
javax_activation_version=1.1.1 javax_activation_version=1.1.1
library_group=dev.inmo library_group=dev.inmo
library_version=0.33.4 library_version=0.34.0
github_release_plugin_version=2.2.12 github_release_plugin_version=2.2.12

View File

@ -1,6 +1,5 @@
# TelegramBotAPI Core # TelegramBotAPI Core
[![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.core/images/download.svg) ](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core)
## What is it? ## What is it?
@ -10,7 +9,7 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
## Compatibility ## Compatibility
This version compatible with [9th of March 2021 update of TelegramBotAPI (version 5.1)](https://core.telegram.org/bots/api-changelog#march-9-2021). This version compatible with [26th of April 2021 update of TelegramBotAPI (version 5.2)](https://core.telegram.org/bots/api-changelog#april-26-2021).
## How to implement library? ## How to implement library?

View File

@ -1,26 +1,20 @@
package dev.inmo.tgbotapi.CommonAbstracts package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode const val CaptionDeprecation = "Captioned interface and others will be removed soon and not recommended to use"
interface Captioned { @Deprecated(CaptionDeprecation)
interface Captioned : Texted {
@Deprecated(CaptionDeprecation)
val caption: String? val caption: String?
get() = text
} }
@Deprecated("This interface is not used in library and will be removed soon") @Deprecated(CaptionDeprecation)
interface CaptionedOutput : Captioned { interface CaptionedInput : Captioned, TextedInput {
val parseMode: ParseMode?
}
interface CaptionedInput : Captioned {
/** /**
* Full list of entities. This list WILL contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] * Full list of entities. This list WILL contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/ */
@Deprecated(CaptionDeprecation)
val captionEntities: List<TextPart> val captionEntities: List<TextPart>
get() = textEntities
} }
/**
* @see CaptionedInput.captionEntities
* @see justTextSources
*/
val CaptionedInput.textSources
get() = captionEntities.justTextSources()

View File

@ -0,0 +1,36 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.payments.abstracts.Currencied
import dev.inmo.tgbotapi.types.payments.abstracts.Priced
interface CommonSendInvoiceData : Titled, Currencied, Priced {
val description: String
val payload: String
val providerToken: String
val maxTipAmount: Int?
val suggestedTipAmounts: List<Int>?
val providerData: String?
val requireName: Boolean
val requirePhoneNumber: Boolean
val requireEmail: Boolean
val requireShippingAddress: Boolean
val shouldSendPhoneNumberToProvider: Boolean
val shouldSendEmailToProvider: Boolean
val priceDependOnShipAddress: Boolean
val photoUrl: String?
val photoSize: Long?
val photoWidth: Int?
val photoHeight: Int?
fun setPhoto(
photoUrl: String,
photoSize: Long? = null,
photoWidth: Int? = null,
photoHeight: Int? = null
)
fun unsetPhoto()
}

View File

@ -1,31 +1,26 @@
package dev.inmo.tgbotapi.CommonAbstracts package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode @Deprecated("Will be removed soon")
interface Explained : Texted {
interface Explained {
val explanation: String? val explanation: String?
get() = text
} }
interface ParsableExplainedOutput : Explained { @Deprecated("Will be removed soon")
val parseMode: ParseMode? interface ParsableExplainedOutput : Explained, TextedOutput
}
interface EntitiesExplainedOutput : Explained { @Deprecated("Will be removed soon")
val entities: List<TextSource>? interface EntitiesExplainedOutput : Explained, EntitiesOutput
}
@Deprecated("Will be removed soon")
interface ExplainedOutput : ParsableExplainedOutput, EntitiesExplainedOutput interface ExplainedOutput : ParsableExplainedOutput, EntitiesExplainedOutput
@Deprecated("Will be removed soon")
interface ExplainedInput : Explained { interface ExplainedInput : Explained {
val textSources: TextSourcesList
/** /**
* Full list of entities. This list WILL contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] * Full list of entities. This list WILL contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/ */
val explanationEntities: List<TextPart> val explanationEntities: List<TextPart>
get() = textSources.toTextParts()
} }
/**
* @see ExplainedInput.explanationEntities
* @see justTextSources
*/
val ExplainedInput.textSources
get() = explanationEntities.justTextSources()

View File

@ -2,7 +2,6 @@ package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourceSerializer import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourceSerializer
import dev.inmo.tgbotapi.types.MessageEntity.textsources.regular import dev.inmo.tgbotapi.types.MessageEntity.textsources.regular
import dev.inmo.tgbotapi.types.MessageEntity.toTextParts
import dev.inmo.tgbotapi.types.captionLength import dev.inmo.tgbotapi.types.captionLength
import dev.inmo.tgbotapi.types.textLength import dev.inmo.tgbotapi.types.textLength
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -44,14 +43,27 @@ interface MultilevelTextSource : TextSource {
} }
} }
@Deprecated("This class will be removed soon. Use TextSources instead")
data class TextPart( data class TextPart(
val range: IntRange, val range: IntRange,
val source: TextSource val source: TextSource
) )
@Deprecated("This method is no longer required to work with TextSources")
fun List<TextPart>.justTextSources() = map { it.source } fun List<TextPart>.justTextSources() = map { it.source }
internal fun List<TextSource>.toTextParts(preOffset: Int = 0): List<TextPart> {
var i = preOffset
return map {
TextPart(
i until (i + it.source.length),
it
).also {
i = it.range.last + 1
}
}
}
fun List<TextSource>.makeString() = joinToString("") { it.source } fun List<TextSource>.makeString() = joinToString("") { it.source }
internal fun MultilevelTextSource.textParts(offset: Int): List<TextPart> = subsources.toTextParts(offset)
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> { fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> {
if (isEmpty()) { if (isEmpty()) {
return emptyList() return emptyList()

View File

@ -5,31 +5,31 @@ import dev.inmo.tgbotapi.types.ParseMode.ParseMode
interface Texted { interface Texted {
val text: String? val text: String?
} }
interface TextedWithTextSources : Texted {
/**
* Full list of [TextSource] built from source[TextedInput.textEntities]
*/
val textSources: List<TextSource>?
}
interface ParsableOutput : Texted { interface ParsableOutput : Texted {
val parseMode: ParseMode? val parseMode: ParseMode?
} }
interface EntitiesOutput : Texted { interface EntitiesOutput : TextedWithTextSources {
val entities: List<TextSource>? val entities: List<TextSource>?
get() = textSources
} }
interface TextedOutput : ParsableOutput, EntitiesOutput interface TextedOutput : ParsableOutput, EntitiesOutput
interface TextedInput : Texted { interface TextedInput : TextedWithTextSources {
override val textSources: List<TextSource>
/** /**
* Here must be full list of entities. This list must contains [TextPart]s with * Here must be full list of entities. This list must contains [TextPart]s with
* [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] in case if source text contains parts of * [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] in case if source text contains parts of
* regular text * regular text
*/ */
val textEntities: List<TextPart> val textEntities: List<TextPart>
get() = textSources.toTextParts()
} }
/**
* Full list of [TextSource] built from source[TextedInput.textEntities]
*
* @see TextedInput.textEntities
* @see justTextSources
*/
val TextedInput.textSources
get() = textEntities.justTextSources()

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.edit.caption package dev.inmo.tgbotapi.requests.edit.caption
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.requests.edit.media.MediaContentMessageResultDeserializer import dev.inmo.tgbotapi.requests.edit.media.MediaContentMessageResultDeserializer
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@ -58,8 +59,8 @@ data class EditChatMessageCaption internal constructor(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<MediaContent>, EditTextChatMessage, EditReplyMessage { ) : EditChatMessage<MediaContent>, EditTextChatMessage, EditReplyMessage {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextSources(text)
} }
override fun method(): String = editMessageCaptionMethod override fun method(): String = editMessageCaptionMethod

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.edit.caption package dev.inmo.tgbotapi.requests.edit.caption
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.* import dev.inmo.tgbotapi.types.MessageEntity.*
@ -47,8 +48,8 @@ data class EditInlineMessageCaption internal constructor(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditTextChatMessage, EditReplyMessage { ) : EditInlineMessage, EditTextChatMessage, EditReplyMessage {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextSources(text)
} }
override fun method(): String = editMessageCaptionMethod override fun method(): String = editMessageCaptionMethod

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.edit.text package dev.inmo.tgbotapi.requests.edit.text
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.requests.send.TextContentMessageResultDeserializer import dev.inmo.tgbotapi.requests.send.TextContentMessageResultDeserializer
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@ -64,8 +65,8 @@ data class EditChatMessageText internal constructor(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<TextContent>, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage { ) : EditChatMessage<TextContent>, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextSources(text)
} }
override fun method(): String = editMessageTextMethod override fun method(): String = editMessageTextMethod

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.edit.text package dev.inmo.tgbotapi.requests.edit.text
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.* import dev.inmo.tgbotapi.types.MessageEntity.*
@ -53,8 +54,8 @@ data class EditInlineMessageText internal constructor(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage { ) : EditInlineMessage, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextSources(text)
} }
override fun method(): String = editMessageTextMethod override fun method(): String = editMessageTextMethod

View File

@ -62,8 +62,8 @@ data class CopyMessage internal constructor(
TextedOutput { TextedOutput {
override val chatId: ChatIdentifier override val chatId: ChatIdentifier
get() = fromChatId get() = fromChatId
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
override fun method(): String = "copyMessage" override fun method(): String = "copyMessage"

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.CommonAbstracts.types.DisableWebPagePreview import dev.inmo.tgbotapi.CommonAbstracts.types.DisableWebPagePreview
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@ -83,8 +84,8 @@ data class SendTextMessage internal constructor(
TextableSendMessageRequest<ContentMessage<TextContent>>, TextableSendMessageRequest<ContentMessage<TextContent>>,
DisableWebPagePreview DisableWebPagePreview
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextSources(text)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
@ -20,7 +21,7 @@ fun SendAnimation(
chatId: ChatIdentifier, chatId: ChatIdentifier,
animation: InputFile, animation: InputFile,
thumb: InputFile? = null, thumb: InputFile? = null,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
duration: Long? = null, duration: Long? = null,
width: Int? = null, width: Int? = null,
@ -39,7 +40,7 @@ fun SendAnimation(
chatId, chatId,
animationAsFileId, animationAsFileId,
thumbAsFileId, thumbAsFileId,
caption, text,
parseMode, parseMode,
null, null,
duration, duration,
@ -144,8 +145,8 @@ data class SendAnimationData internal constructor(
DuratedSendMessageRequest<ContentMessage<AnimationContent>>, DuratedSendMessageRequest<ContentMessage<AnimationContent>>,
SizedSendMessageRequest<ContentMessage<AnimationContent>> SizedSendMessageRequest<ContentMessage<AnimationContent>>
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -20,7 +20,7 @@ fun SendAudio(
chatId: ChatIdentifier, chatId: ChatIdentifier,
audio: InputFile, audio: InputFile,
thumb: InputFile? = null, thumb: InputFile? = null,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
duration: Long? = null, duration: Long? = null,
performer: String? = null, performer: String? = null,
@ -39,7 +39,7 @@ fun SendAudio(
chatId, chatId,
audioAsFileId, audioAsFileId,
thumbAsFileId, thumbAsFileId,
caption, text,
parseMode, parseMode,
null, null,
duration, duration,
@ -145,8 +145,8 @@ data class SendAudioData internal constructor(
DuratedSendMessageRequest<ContentMessage<AudioContent>>, DuratedSendMessageRequest<ContentMessage<AudioContent>>,
Performerable Performerable
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
@ -29,7 +30,7 @@ fun SendDocument(
chatId: ChatIdentifier, chatId: ChatIdentifier,
document: InputFile, document: InputFile,
thumb: InputFile? = null, thumb: InputFile? = null,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
@ -46,7 +47,7 @@ fun SendDocument(
chatId, chatId,
documentAsFileId, documentAsFileId,
thumbAsFileId, thumbAsFileId,
caption, text,
parseMode, parseMode,
null, null,
disableNotification, disableNotification,
@ -157,8 +158,8 @@ data class SendDocumentData internal constructor(
TextableSendMessageRequest<ContentMessage<DocumentContent>>, TextableSendMessageRequest<ContentMessage<DocumentContent>>,
ThumbedSendMessageRequest<ContentMessage<DocumentContent>> ThumbedSendMessageRequest<ContentMessage<DocumentContent>>
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
@ -18,7 +19,7 @@ import kotlinx.serialization.*
fun SendPhoto( fun SendPhoto(
chatId: ChatIdentifier, chatId: ChatIdentifier,
photo: InputFile, photo: InputFile,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
@ -28,7 +29,7 @@ fun SendPhoto(
val data = SendPhotoData( val data = SendPhotoData(
chatId, chatId,
(photo as? FileId) ?.fileId, (photo as? FileId) ?.fileId,
caption, text,
parseMode, parseMode,
null, null,
disableNotification, disableNotification,
@ -100,8 +101,8 @@ data class SendPhotoData internal constructor(
ReplyingMarkupSendMessageRequest<ContentMessage<PhotoContent>>, ReplyingMarkupSendMessageRequest<ContentMessage<PhotoContent>>,
TextableSendMessageRequest<ContentMessage<PhotoContent>> TextableSendMessageRequest<ContentMessage<PhotoContent>>
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
@ -20,7 +21,7 @@ fun SendVideo(
chatId: ChatIdentifier, chatId: ChatIdentifier,
video: InputFile, video: InputFile,
thumb: InputFile? = null, thumb: InputFile? = null,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
duration: Long? = null, duration: Long? = null,
width: Int? = null, width: Int? = null,
@ -40,7 +41,7 @@ fun SendVideo(
chatId, chatId,
videoAsFileId, videoAsFileId,
thumbAsFileId, thumbAsFileId,
caption, text,
parseMode, parseMode,
null, null,
duration, duration,
@ -150,8 +151,8 @@ data class SendVideoData internal constructor(
DuratedSendMessageRequest<ContentMessage<VideoContent>>, DuratedSendMessageRequest<ContentMessage<VideoContent>>,
SizedSendMessageRequest<ContentMessage<VideoContent>> SizedSendMessageRequest<ContentMessage<VideoContent>>
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
@ -19,7 +20,7 @@ import kotlinx.serialization.*
fun SendVoice( fun SendVoice(
chatId: ChatIdentifier, chatId: ChatIdentifier,
voice: InputFile, voice: InputFile,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
duration: Long? = null, duration: Long? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
@ -33,7 +34,7 @@ fun SendVoice(
val data = SendVoiceData( val data = SendVoiceData(
chatId, chatId,
voiceAsFileId, voiceAsFileId,
caption, text,
parseMode, parseMode,
null, null,
duration, duration,
@ -120,8 +121,8 @@ data class SendVoiceData internal constructor(
TextableSendMessageRequest<ContentMessage<VoiceContent>>, TextableSendMessageRequest<ContentMessage<VoiceContent>>,
DuratedSendMessageRequest<ContentMessage<VoiceContent>> DuratedSendMessageRequest<ContentMessage<VoiceContent>>
{ {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.requests.send.payments package dev.inmo.tgbotapi.requests.send.payments
import dev.inmo.tgbotapi.CommonAbstracts.CommonSendInvoiceData
import dev.inmo.tgbotapi.CommonAbstracts.types.* import dev.inmo.tgbotapi.CommonAbstracts.types.*
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@ -9,7 +10,7 @@ import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializ
import dev.inmo.tgbotapi.types.message.payments.InvoiceContent import dev.inmo.tgbotapi.types.message.payments.InvoiceContent
import dev.inmo.tgbotapi.types.payments.LabeledPrice import dev.inmo.tgbotapi.types.payments.LabeledPrice
import dev.inmo.tgbotapi.types.payments.LabeledPricesSerializer import dev.inmo.tgbotapi.types.payments.LabeledPricesSerializer
import dev.inmo.tgbotapi.types.payments.abstracts.* import dev.inmo.tgbotapi.types.payments.abstracts.Currency
import kotlinx.serialization.* import kotlinx.serialization.*
private val invoiceMessageSerializer: DeserializationStrategy<ContentMessage<InvoiceContent>> private val invoiceMessageSerializer: DeserializationStrategy<ContentMessage<InvoiceContent>>
@ -23,36 +24,40 @@ data class SendInvoice(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatId, override val chatId: ChatId,
@SerialName(titleField) @SerialName(titleField)
val title: String, override val title: String,
@SerialName(descriptionField) @SerialName(descriptionField)
val description: String, override val description: String,
@SerialName(payloadField) @SerialName(payloadField)
val payload: String, override val payload: String,
@SerialName(providerTokenField) @SerialName(providerTokenField)
val providerToken: String, override val providerToken: String,
@SerialName(startParameterField)
val startParameter: StartParameter,
@SerialName(currencyField) @SerialName(currencyField)
override val currency: Currency, override val currency: Currency,
@Serializable(LabeledPricesSerializer::class) @Serializable(LabeledPricesSerializer::class)
@SerialName(pricesField) @SerialName(pricesField)
override val prices: List<LabeledPrice>, override val prices: List<LabeledPrice>,
@SerialName(maxTipAmountField)
override val maxTipAmount: Int? = null,
@SerialName(suggestedTipAmountsField)
override val suggestedTipAmounts: List<Int>? = null,
@SerialName(startParameterField)
val startParameter: StartParameter? = null,
@SerialName(providerDataField) @SerialName(providerDataField)
val providerData: String? = null, override val providerData: String? = null,
@SerialName(requireNameField) @SerialName(requireNameField)
val requireName: Boolean = false, override val requireName: Boolean = false,
@SerialName(requirePhoneNumberField) @SerialName(requirePhoneNumberField)
val requirePhoneNumber: Boolean = false, override val requirePhoneNumber: Boolean = false,
@SerialName(requireEmailField) @SerialName(requireEmailField)
val requireEmail: Boolean = false, override val requireEmail: Boolean = false,
@SerialName(requireShippingAddressField) @SerialName(requireShippingAddressField)
val requireShippingAddress: Boolean = false, override val requireShippingAddress: Boolean = false,
@SerialName(shouldSendPhoneNumberToProviderField) @SerialName(shouldSendPhoneNumberToProviderField)
val shouldSendPhoneNumberToProvider: Boolean = false, override val shouldSendPhoneNumberToProvider: Boolean = false,
@SerialName(shouldSendEmailToProviderField) @SerialName(shouldSendEmailToProviderField)
val shouldSendEmailToProvider: Boolean = false, override val shouldSendEmailToProvider: Boolean = false,
@SerialName(priceDependOnShipAddressField) @SerialName(priceDependOnShipAddressField)
val priceDependOnShipAddress: Boolean = false, override val priceDependOnShipAddress: Boolean = false,
@SerialName(disableNotificationField) @SerialName(disableNotificationField)
override val disableNotification: Boolean = false, override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField) @SerialName(replyToMessageIdField)
@ -61,8 +66,7 @@ data class SendInvoice(
override val allowSendingWithoutReply: Boolean? = null, override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : Currencied, ) : CommonSendInvoiceData,
Priced,
ChatRequest, ChatRequest,
DisableNotification, DisableNotification,
ReplyMessageId, ReplyMessageId,
@ -75,24 +79,35 @@ data class SendInvoice(
get() = serializer() get() = serializer()
@SerialName(photoUrlField) @SerialName(photoUrlField)
var photoUrl: String? = null override var photoUrl: String? = null
private set private set
@SerialName(photoSizeField) @SerialName(photoSizeField)
var photoSize: Long? = null override var photoSize: Long? = null
private set private set
@SerialName(photoWidthField) @SerialName(photoWidthField)
var photoWidth: Int? = null override var photoWidth: Int? = null
private set private set
@SerialName(photoHeightField) @SerialName(photoHeightField)
var photoHeight: Int? = null override var photoHeight: Int? = null
private set private set
fun setPhoto( init {
suggestedTipAmounts ?.let { _ ->
require(suggestedTipAmounts.size in suggestedTipAmountsLimit)
maxTipAmount ?.let { _ ->
require(
suggestedTipAmounts.none { it > maxTipAmount }
)
}
}
}
override fun setPhoto(
photoUrl: String, photoUrl: String,
photoSize: Long? = null, photoSize: Long?,
photoWidth: Int? = null, photoWidth: Int?,
photoHeight: Int? = null photoHeight: Int?
) { ) {
this.photoUrl = photoUrl this.photoUrl = photoUrl
this.photoSize = photoSize this.photoSize = photoSize
@ -100,7 +115,7 @@ data class SendInvoice(
this.photoHeight = photoHeight this.photoHeight = photoHeight
} }
fun unsetPhoto() { override fun unsetPhoto() {
photoUrl = null photoUrl = null
photoSize = null photoSize = null
photoWidth = null photoWidth = null

View File

@ -338,7 +338,7 @@ data class SendQuizPoll internal constructor(
@SerialName(isClosedField) @SerialName(isClosedField)
override val isClosed: Boolean = false, override val isClosed: Boolean = false,
@SerialName(explanationField) @SerialName(explanationField)
override val explanation: String? = null, override val text: String? = null,
@SerialName(explanationParseModeField) @SerialName(explanationParseModeField)
override val parseMode: ParseMode? = null, override val parseMode: ParseMode? = null,
@SerialName(explanationEntitiesField) @SerialName(explanationEntitiesField)
@ -355,12 +355,12 @@ data class SendQuizPoll internal constructor(
override val allowSendingWithoutReply: Boolean? = null, override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null override val replyMarkup: KeyboardMarkup? = null
) : SendPoll(), ExplainedOutput { ) : SendPoll(), ExplainedOutput, TextedOutput {
override val type: String = quizPollType override val type: String = quizPollType
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(explanation ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {
@ -371,9 +371,9 @@ data class SendQuizPoll internal constructor(
throw IllegalArgumentException("Correct option id must be in range of $correctOptionIdRange, but actual " + throw IllegalArgumentException("Correct option id must be in range of $correctOptionIdRange, but actual " +
"value is $correctOptionId") "value is $correctOptionId")
} }
if (explanation != null && explanation.length !in explanationLimit) { if (text != null && text.length !in explanationLimit) {
error("Quiz poll explanation size must be in range $explanationLimit," + error("Quiz poll explanation size must be in range $explanationLimit," +
"but actual explanation contains ${explanation.length} symbols") "but actual explanation contains ${text.length} symbols")
} }
} }
} }

View File

@ -80,6 +80,8 @@ val openPeriodPollSecondsLimit = 5 .. 600
val membersLimit = 1 .. 99999 val membersLimit = 1 .. 99999
val suggestedTipAmountsLimit = 1 .. 4
const val botActionActualityTime: Seconds = 5 const val botActionActualityTime: Seconds = 5
// Made as lazy for correct work in K/JS // Made as lazy for correct work in K/JS
@ -315,6 +317,10 @@ const val xShiftField = "x_shift"
const val yShiftField = "y_shift" const val yShiftField = "y_shift"
const val scaleField = "scale" const val scaleField = "scale"
const val maxTipAmountField = "max_tip_amount"
const val suggestedTipAmountsField = "suggested_tip_amounts"
const val chatTypeField = "chat_type"
const val explanationEntitiesField = "explanation_entities" const val explanationEntitiesField = "explanation_entities"
const val explanationParseModeField = "explanation_parse_mode" const val explanationParseModeField = "explanation_parse_mode"
const val openPeriodField = "open_period" const val openPeriodField = "open_period"
@ -349,6 +355,7 @@ const val providerPaymentChargeIdField = "provider_payment_charge_id"
const val providerTokenField = "provider_token" const val providerTokenField = "provider_token"
const val providerDataField = "provider_data" const val providerDataField = "provider_data"
const val usersField = "users" const val usersField = "users"
const val startDateField = "start_date"
const val requireNameField = "need_name" const val requireNameField = "need_name"
const val requirePhoneNumberField = "need_phone_number" const val requirePhoneNumberField = "need_phone_number"

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio.InlineQueryResultAudioCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio.InlineQueryResultAudioCached
@ -48,7 +49,7 @@ data class InlineQueryResultAudioCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultAudioCached { ) : InlineQueryResultAudioCached {
override val type: String = inlineQueryResultAudioType override val type: String = inlineQueryResultAudioType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio.InlineQueryResultAudio import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio.InlineQueryResultAudio
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio.inlineQueryResultAudioType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio.inlineQueryResultAudioType
@ -59,7 +60,7 @@ data class InlineQueryResultAudioImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultAudio { ) : InlineQueryResultAudio {
override val type: String = inlineQueryResultAudioType override val type: String = inlineQueryResultAudioType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document.InlineQueryResultDocumentCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document.InlineQueryResultDocumentCached
@ -56,7 +57,7 @@ data class InlineQueryResultDocumentCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultDocumentCached { ) : InlineQueryResultDocumentCached {
override val type: String = inlineQueryResultDocumentType override val type: String = inlineQueryResultDocumentType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document.InlineQueryResultDocument import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document.InlineQueryResultDocument
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document.inlineQueryResultDocumentType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document.inlineQueryResultDocumentType
@ -73,7 +74,7 @@ data class InlineQueryResultDocumentImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultDocument { ) : InlineQueryResultDocument {
override val type: String = inlineQueryResultDocumentType override val type: String = inlineQueryResultDocumentType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif.InlineQueryResultGifCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif.InlineQueryResultGifCached
@ -52,7 +53,7 @@ data class InlineQueryResultGifCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultGifCached { ) : InlineQueryResultGifCached {
override val type: String = inlineQueryResultGifType override val type: String = inlineQueryResultGifType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif.InlineQueryResultGif import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif.InlineQueryResultGif
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif.inlineQueryResultGifType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif.inlineQueryResultGifType
@ -72,8 +73,8 @@ data class InlineQueryResultGifImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultGif { ) : InlineQueryResultGif {
override val type: String = inlineQueryResultGifType override val type: String = inlineQueryResultGifType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif.InlineQueryResultMpeg4GifCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif.InlineQueryResultMpeg4GifCached
@ -52,7 +53,7 @@ data class InlineQueryResultMpeg4GifCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultMpeg4GifCached { ) : InlineQueryResultMpeg4GifCached {
override val type: String = inlineQueryResultMpeg4GifType override val type: String = inlineQueryResultMpeg4GifType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif.InlineQueryResultMpeg4Gif import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif.InlineQueryResultMpeg4Gif
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif.inlineQueryResultMpeg4GifType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif.inlineQueryResultMpeg4GifType
@ -72,8 +73,8 @@ data class InlineQueryResultMpeg4GifImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultMpeg4Gif { ) : InlineQueryResultMpeg4Gif {
override val type: String = inlineQueryResultMpeg4GifType override val type: String = inlineQueryResultMpeg4GifType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
init { init {

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo.InlineQueryResultPhotoCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo.InlineQueryResultPhotoCached
@ -56,7 +57,7 @@ data class InlineQueryResultPhotoCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultPhotoCached { ) : InlineQueryResultPhotoCached {
override val type: String = inlineQueryResultPhotoType override val type: String = inlineQueryResultPhotoType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo.InlineQueryResultPhoto import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo.InlineQueryResultPhoto
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo.inlineQueryResultPhotoType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo.inlineQueryResultPhotoType
@ -67,7 +68,7 @@ data class InlineQueryResultPhotoImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultPhoto { ) : InlineQueryResultPhoto {
override val type: String = inlineQueryResultPhotoType override val type: String = inlineQueryResultPhotoType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video.InlineQueryResultVideoCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video.InlineQueryResultVideoCached
@ -56,7 +57,7 @@ data class InlineQueryResultVideoCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultVideoCached { ) : InlineQueryResultVideoCached {
override val type: String = inlineQueryResultVideoType override val type: String = inlineQueryResultVideoType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video.InlineQueryResultVideo import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video.InlineQueryResultVideo
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video.inlineQueryResultVideoType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video.inlineQueryResultVideoType
@ -77,7 +78,7 @@ data class InlineQueryResultVideoImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultVideo { ) : InlineQueryResultVideo {
override val type: String = inlineQueryResultVideoType override val type: String = inlineQueryResultVideoType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice.InlineQueryResultVoiceCached import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice.InlineQueryResultVoiceCached
@ -52,7 +53,7 @@ data class InlineQueryResultVoiceCachedImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultVoiceCached { ) : InlineQueryResultVoiceCached {
override val type: String = inlineQueryResultVoiceType override val type: String = inlineQueryResultVoiceType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice.InlineQueryResultVoice import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice.InlineQueryResultVoice
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice.inlineQueryResultVoiceType import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice.inlineQueryResultVoiceType
@ -65,7 +66,7 @@ data class InlineQueryResultVoiceImpl internal constructor(
override val inputMessageContent: InputMessageContent? = null override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultVoice { ) : InlineQueryResultVoice {
override val type: String = inlineQueryResultVoiceType override val type: String = inlineQueryResultVoiceType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
} }

View File

@ -0,0 +1,80 @@
package dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent
import dev.inmo.tgbotapi.CommonAbstracts.CommonSendInvoiceData
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InputMessageContent
import dev.inmo.tgbotapi.types.payments.LabeledPrice
import dev.inmo.tgbotapi.types.payments.LabeledPricesSerializer
import dev.inmo.tgbotapi.types.payments.abstracts.Currency
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
class InputInvoiceMessageContent(
@SerialName(titleField)
override val title: String,
@SerialName(descriptionField)
override val description: String,
@SerialName(payloadField)
override val payload: String,
@SerialName(providerTokenField)
override val providerToken: String,
@SerialName(currencyField)
override val currency: Currency,
@Serializable(LabeledPricesSerializer::class)
@SerialName(pricesField)
override val prices: List<LabeledPrice>,
@SerialName(maxTipAmountField)
override val maxTipAmount: Int? = null,
@SerialName(suggestedTipAmountsField)
override val suggestedTipAmounts: List<Int>? = null,
@SerialName(providerDataField)
override val providerData: String? = null,
@SerialName(requireNameField)
override val requireName: Boolean = false,
@SerialName(requirePhoneNumberField)
override val requirePhoneNumber: Boolean = false,
@SerialName(requireEmailField)
override val requireEmail: Boolean = false,
@SerialName(requireShippingAddressField)
override val requireShippingAddress: Boolean = false,
@SerialName(shouldSendPhoneNumberToProviderField)
override val shouldSendPhoneNumberToProvider: Boolean = false,
@SerialName(shouldSendEmailToProviderField)
override val shouldSendEmailToProvider: Boolean = false,
@SerialName(priceDependOnShipAddressField)
override val priceDependOnShipAddress: Boolean = false
) : InputMessageContent, CommonSendInvoiceData {
@SerialName(photoUrlField)
override var photoUrl: String? = null
private set
@SerialName(photoSizeField)
override var photoSize: Long? = null
private set
@SerialName(photoWidthField)
override var photoWidth: Int? = null
private set
@SerialName(photoHeightField)
override var photoHeight: Int? = null
private set
override fun setPhoto(
photoUrl: String,
photoSize: Long?,
photoWidth: Int?,
photoHeight: Int?
) {
this.photoUrl = photoUrl
this.photoSize = photoSize
this.photoWidth = photoWidth
this.photoHeight = photoHeight
}
override fun unsetPhoto() {
photoUrl = null
photoSize = null
photoWidth = null
photoHeight = null
}
}

View File

@ -38,7 +38,7 @@ data class InputTextMessageContent internal constructor(
@SerialName(disableWebPagePreviewField) @SerialName(disableWebPagePreviewField)
override val disableWebPagePreview: Boolean? = null override val disableWebPagePreview: Boolean? = null
) : TextedOutput, DisableWebPagePreview, InputMessageContent { ) : TextedOutput, DisableWebPagePreview, InputMessageContent {
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextSources(text)
} }
} }

View File

@ -17,6 +17,7 @@ internal object InputMessageContentSerializer : KSerializer<InputMessageContent>
is InputLocationMessageContent -> InputLocationMessageContent.serializer().serialize(encoder, value) is InputLocationMessageContent -> InputLocationMessageContent.serializer().serialize(encoder, value)
is InputTextMessageContent -> InputTextMessageContent.serializer().serialize(encoder, value) is InputTextMessageContent -> InputTextMessageContent.serializer().serialize(encoder, value)
is InputVenueMessageContent -> InputVenueMessageContent.serializer().serialize(encoder, value) is InputVenueMessageContent -> InputVenueMessageContent.serializer().serialize(encoder, value)
is InputInvoiceMessageContent -> InputInvoiceMessageContent.serializer().serialize(encoder, value)
else -> throw IllegalArgumentException("Unknown for serializing InputContactMessageContent") else -> throw IllegalArgumentException("Unknown for serializing InputContactMessageContent")
} }
} }

View File

@ -2,10 +2,12 @@ package dev.inmo.tgbotapi.types.InlineQueries.abstracts
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.chat.ChatType
interface InlineQuery { interface InlineQuery {
val id: InlineQueryIdentifier val id: InlineQueryIdentifier
val from: User val from: User
val query: String val query: String
val offset: String val offset: String
val chatType: ChatType?
} }

View File

@ -3,10 +3,12 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.chat.ChatType
data class BaseInlineQuery( data class BaseInlineQuery(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
override val from: User, override val from: User,
override val query: String, override val query: String,
override val offset: String override val offset: String,
override val chatType: ChatType?
) : InlineQuery ) : InlineQuery

View File

@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.chat.ChatType
import dev.inmo.tgbotapi.types.location.Location import dev.inmo.tgbotapi.types.location.Location
data class LocationInlineQuery( data class LocationInlineQuery(
@ -10,5 +11,6 @@ data class LocationInlineQuery(
override val from: User, override val from: User,
override val query: String, override val query: String,
override val offset: String, override val offset: String,
override val chatType: ChatType?,
val location: Location val location: Location
) : InlineQuery ) : InlineQuery

View File

@ -1,6 +1,8 @@
package dev.inmo.tgbotapi.types.InlineQueries.query package dev.inmo.tgbotapi.types.InlineQueries.query
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.ChatType
import dev.inmo.tgbotapi.types.chat.ChatTypeSerializer
import dev.inmo.tgbotapi.types.location.Location import dev.inmo.tgbotapi.types.location.Location
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -15,12 +17,15 @@ internal data class RawInlineQuery(
val query: String, val query: String,
@SerialName(offsetField) @SerialName(offsetField)
val offset: String, val offset: String,
@SerialName(chatTypeField)
@Serializable(ChatTypeSerializer::class)
val chatType: ChatType? = null,
@SerialName(locationField) @SerialName(locationField)
val location: Location? = null val location: Location? = null
) { ) {
val asInlineQuery by lazy { val asInlineQuery by lazy {
location ?.let { location ?.let {
LocationInlineQuery(id, from, query, offset, location) LocationInlineQuery(id, from, query, offset, chatType, location)
} ?: BaseInlineQuery(id, from, query, offset) } ?: BaseInlineQuery(id, from, query, offset, chatType)
} }
} }

View File

@ -44,8 +44,8 @@ data class InputMediaAnimation internal constructor(
override val thumb: InputFile? = null override val thumb: InputFile? = null
) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, TextedOutput { ) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, TextedOutput {
override val type: String = "animation" override val type: String = "animation"
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
@SerialName(mediaField) @SerialName(mediaField)

View File

@ -50,8 +50,8 @@ data class InputMediaAudio internal constructor(
override val thumb: InputFile? = null override val thumb: InputFile? = null
) : InputMedia, AudioMediaGroupMemberInputMedia, DuratedInputMedia, ThumbedInputMedia, TitledInputMedia, Performerable { ) : InputMedia, AudioMediaGroupMemberInputMedia, DuratedInputMedia, ThumbedInputMedia, TitledInputMedia, Performerable {
override val type: String = audioInputMediaType override val type: String = audioInputMediaType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this) override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this)
@ -62,12 +62,12 @@ data class InputMediaAudio internal constructor(
} }
fun AudioFile.toInputMediaAudio( fun AudioFile.toInputMediaAudio(
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
title: String? = this.title title: String? = this.title
): InputMediaAudio = InputMediaAudio( ): InputMediaAudio = InputMediaAudio(
fileId, fileId,
caption, text,
parseMode, parseMode,
duration, duration,
performer, performer,

View File

@ -13,11 +13,11 @@ internal const val documentInputMediaType = "document"
fun InputMediaDocument( fun InputMediaDocument(
file: InputFile, file: InputFile,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
thumb: InputFile? = null, thumb: InputFile? = null,
disableContentTypeDetection: Boolean? = null disableContentTypeDetection: Boolean? = null
) = InputMediaDocument(file, caption, parseMode, null, thumb, disableContentTypeDetection) ) = InputMediaDocument(file, text, parseMode, null, thumb, disableContentTypeDetection)
fun InputMediaDocument( fun InputMediaDocument(
file: InputFile, file: InputFile,
@ -50,8 +50,8 @@ data class InputMediaDocument internal constructor(
val disableContentTypeDetection: Boolean? = null val disableContentTypeDetection: Boolean? = null
) : InputMedia, DocumentMediaGroupMemberInputMedia, ThumbedInputMedia { ) : InputMedia, DocumentMediaGroupMemberInputMedia, ThumbedInputMedia {
override val type: String = documentInputMediaType override val type: String = documentInputMediaType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this) override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this)
@ -62,11 +62,11 @@ data class InputMediaDocument internal constructor(
} }
fun DocumentFile.toInputMediaDocument( fun DocumentFile.toInputMediaDocument(
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null parseMode: ParseMode? = null
) = InputMediaDocument( ) = InputMediaDocument(
fileId, fileId,
caption, text,
parseMode, parseMode,
thumb ?.fileId thumb ?.fileId
) )

View File

@ -34,8 +34,8 @@ data class InputMediaPhoto internal constructor(
private val rawEntities: List<RawMessageEntity>? = null private val rawEntities: List<RawMessageEntity>? = null
) : InputMedia, VisualMediaGroupMemberInputMedia { ) : InputMedia, VisualMediaGroupMemberInputMedia {
override val type: String = photoInputMediaType override val type: String = photoInputMediaType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this) override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this)
@ -46,11 +46,11 @@ data class InputMediaPhoto internal constructor(
} }
fun PhotoSize.toInputMediaPhoto( fun PhotoSize.toInputMediaPhoto(
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null parseMode: ParseMode? = null
): InputMediaPhoto = InputMediaPhoto( ): InputMediaPhoto = InputMediaPhoto(
fileId, fileId,
caption, text,
parseMode parseMode
) )

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.InputMedia package dev.inmo.tgbotapi.types.InputMedia
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.requests.abstracts.InputFile import dev.inmo.tgbotapi.requests.abstracts.InputFile
import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@ -45,8 +46,8 @@ data class InputMediaVideo internal constructor (
override val thumb: InputFile? = null override val thumb: InputFile? = null
) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, VisualMediaGroupMemberInputMedia { ) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, VisualMediaGroupMemberInputMedia {
override val type: String = videoInputMediaType override val type: String = videoInputMediaType
override val entities: List<TextSource>? by lazy { override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextSources(text ?: return@lazy null)
} }
override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this) override fun serialize(format: StringFormat): String = format.encodeToString(serializer(), this)

View File

@ -1,10 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.MultilevelTextSource
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.types.MessageEntity.textsources.* import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.utils.internal.fullListOfSubSource
import dev.inmo.tgbotapi.utils.internal.shiftSourcesToTheLeft
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@ -15,70 +14,115 @@ internal data class RawMessageEntity(
val url: String? = null, val url: String? = null,
val user: User? = null, val user: User? = null,
val language: String? = null val language: String? = null
) ) {
internal val range by lazy {
internal fun RawMessageEntity.asTextParts( offset until (offset + length)
source: String,
subParts: List<TextPart>
): List<TextPart> {
val sourceSubstring: String = source.substring(offset, offset + length)
val range = offset until (offset + length)
val shiftedSubSources = sourceSubstring.fullListOfSubSource(subParts.shiftSourcesToTheLeft(offset)).justTextSources()
return when (type) {
"mention" -> MentionTextSource(sourceSubstring, shiftedSubSources)
"hashtag" -> HashTagTextSource(sourceSubstring, shiftedSubSources)
"cashtag" -> CashTagTextSource(sourceSubstring, shiftedSubSources)
"bot_command" -> BotCommandTextSource(sourceSubstring)
"url" -> URLTextSource(sourceSubstring)
"email" -> EMailTextSource(sourceSubstring, shiftedSubSources)
"phone_number" -> PhoneNumberTextSource(sourceSubstring, shiftedSubSources)
"bold" -> BoldTextSource(sourceSubstring, shiftedSubSources)
"italic" -> ItalicTextSource(sourceSubstring, shiftedSubSources)
"code" -> CodeTextSource(sourceSubstring)
"pre" -> PreTextSource(sourceSubstring, language)
"text_link" -> TextLinkTextSource(sourceSubstring, url ?: throw IllegalStateException("URL must not be null for text link"))
"text_mention" -> TextMentionTextSource(sourceSubstring, user ?: throw IllegalStateException("User must not be null for text mention"), shiftedSubSources)
"underline" -> UnderlineTextSource(sourceSubstring, shiftedSubSources)
"strikethrough" -> StrikethroughTextSource(sourceSubstring, shiftedSubSources)
else -> RegularTextSource(sourceSubstring)
}.let {
val part = TextPart(range, it)
if (it !is MultilevelTextSource && subParts.isNotEmpty()) {
(subParts + part).sortedBy { currentPart -> currentPart.range.first }
} else {
listOf(part)
}
} }
} }
internal fun createTextPart(originalFullString: String, entities: RawMessageEntities): List<TextPart> { internal fun RawMessageEntity.asTextSource(
val mutableEntities = entities.toMutableList() source: String,
mutableEntities.sortBy { it.offset } subParts: List<TextSource>
val resultList = mutableListOf<TextPart>() ): TextSource {
val sourceSubstring: String = source.substring(range)
val subPartsWithRegulars by lazy {
subParts.fillWithRegulars(sourceSubstring)
}
return when (type) {
"mention" -> MentionTextSource(sourceSubstring, subPartsWithRegulars)
"hashtag" -> HashTagTextSource(sourceSubstring, subPartsWithRegulars)
"cashtag" -> CashTagTextSource(sourceSubstring, subPartsWithRegulars)
"bot_command" -> BotCommandTextSource(sourceSubstring)
"url" -> URLTextSource(sourceSubstring)
"email" -> EMailTextSource(sourceSubstring, subPartsWithRegulars)
"phone_number" -> PhoneNumberTextSource(sourceSubstring, subPartsWithRegulars)
"bold" -> BoldTextSource(sourceSubstring, subPartsWithRegulars)
"italic" -> ItalicTextSource(sourceSubstring, subPartsWithRegulars)
"code" -> CodeTextSource(sourceSubstring)
"pre" -> PreTextSource(sourceSubstring, language)
"text_link" -> TextLinkTextSource(sourceSubstring, url ?: throw IllegalStateException("URL must not be null for text link"))
"text_mention" -> TextMentionTextSource(sourceSubstring, user ?: throw IllegalStateException("User must not be null for text mention"), subPartsWithRegulars)
"underline" -> UnderlineTextSource(sourceSubstring, subPartsWithRegulars)
"strikethrough" -> StrikethroughTextSource(sourceSubstring, subPartsWithRegulars)
else -> RegularTextSource(sourceSubstring)
}
}
private inline operator fun <T : Comparable<T>> ClosedRange<T>.contains(other: ClosedRange<T>): Boolean {
return start <= other.start && endInclusive >= other.endInclusive
}
internal fun List<TextSource>.fillWithRegulars(source: String): List<TextSource> {
var index = 0
val result = mutableListOf<TextSource>()
for (i in 0 until size) {
val textSource = get(i)
val thisSourceInStart = source.startsWith(textSource.source, index)
if (!thisSourceInStart) {
val regularEndIndex = source.indexOf(textSource.source)
result.add(regular(source.substring(index, regularEndIndex)))
index = regularEndIndex
}
result.add(textSource)
index += textSource.source.length
}
if (index != source.length) {
result.add(regular(source.substring(index, source.length)))
}
return result
}
private fun createTextSources(originalFullString: String, entities: RawMessageEntities): List<TextSource> {
val mutableEntities = entities.toMutableList().apply { sortBy { it.offset } }
val resultList = mutableListOf<TextSource>()
while (mutableEntities.isNotEmpty()) { while (mutableEntities.isNotEmpty()) {
val currentFirst = mutableEntities.removeAt(0) var parent = mutableEntities.removeFirst()
val subEntities = if (mutableEntities.isNotEmpty()) { val subentities = mutableListOf<RawMessageEntity>()
val lastIndex = currentFirst.offset + currentFirst.length val toAddCutted = mutableListOf<RawMessageEntity>()
val subEntities = mutableListOf<RawMessageEntity>() while (mutableEntities.isNotEmpty()) {
while (mutableEntities.isNotEmpty()) { val potentialParent = mutableEntities.first()
val currentPossibleSubEntity = mutableEntities.first() when {
if (currentPossibleSubEntity.offset < lastIndex) { potentialParent.range.first > parent.range.last -> break
subEntities.add(currentPossibleSubEntity) potentialParent.range in parent.range -> {
mutableEntities.removeAt(0) subentities.add(potentialParent)
} else { }
break potentialParent.offset == parent.offset && potentialParent.length > parent.length -> {
subentities.add(parent)
parent = potentialParent
}
else -> { // need to cut
toAddCutted.add(potentialParent)
} }
} }
subEntities mutableEntities.remove(potentialParent)
} else {
emptyList<RawMessageEntity>()
} }
val subtextSources = if (subentities.isNotEmpty()) {
resultList.addAll( mutableEntities.removeAll(subentities)
currentFirst.asTextParts( if (toAddCutted.isNotEmpty()) {
val borderIndex = parent.range.last + 1
mutableEntities.addAll(
0,
toAddCutted.map {
val firstLength = borderIndex - it.offset
subentities.add(it.copy(length = firstLength))
it.copy(
offset = borderIndex,
length = it.length - firstLength
)
}
)
}
createTextSources(originalFullString, subentities)
} else {
emptyList()
}
resultList.add(
parent.asTextSource(
originalFullString, originalFullString,
createTextPart(originalFullString, subEntities) subtextSources
) )
) )
} }
@ -86,46 +130,41 @@ internal fun createTextPart(originalFullString: String, entities: RawMessageEnti
return resultList return resultList
} }
internal fun TextPart.asRawMessageEntities(): List<RawMessageEntity> { internal fun TextSource.toRawMessageEntities(offset: Int = 0): List<RawMessageEntity> {
val source = source val source = source
val length = range.last - range.first + 1 val length = source.length
return listOfNotNull( return listOfNotNull(
when (source) { when (this) {
is MentionTextSource -> RawMessageEntity("mention", range.first, length) is MentionTextSource -> RawMessageEntity("mention", offset, length)
is HashTagTextSource -> RawMessageEntity("hashtag", range.first, length) is HashTagTextSource -> RawMessageEntity("hashtag", offset, length)
is CashTagTextSource -> RawMessageEntity("cashtag", range.first, length) is CashTagTextSource -> RawMessageEntity("cashtag", offset, length)
is BotCommandTextSource -> RawMessageEntity("bot_command", range.first, length) is BotCommandTextSource -> RawMessageEntity("bot_command", offset, length)
is URLTextSource -> RawMessageEntity("url", range.first, length) is URLTextSource -> RawMessageEntity("url", offset, length)
is EMailTextSource -> RawMessageEntity("email", range.first, length) is EMailTextSource -> RawMessageEntity("email", offset, length)
is PhoneNumberTextSource -> RawMessageEntity("phone_number", range.first, length) is PhoneNumberTextSource -> RawMessageEntity("phone_number", offset, length)
is BoldTextSource -> RawMessageEntity("bold", range.first, length) is BoldTextSource -> RawMessageEntity("bold", offset, length)
is ItalicTextSource -> RawMessageEntity("italic", range.first, length) is ItalicTextSource -> RawMessageEntity("italic", offset, length)
is CodeTextSource -> RawMessageEntity("code", range.first, length) is CodeTextSource -> RawMessageEntity("code", offset, length)
is PreTextSource -> RawMessageEntity("pre", range.first, length, language = source.language) is PreTextSource -> RawMessageEntity("pre", offset, length, language = language)
is TextLinkTextSource -> RawMessageEntity("text_link", range.first, length, source.url) is TextLinkTextSource -> RawMessageEntity("text_link", offset, length, url)
is TextMentionTextSource -> RawMessageEntity("text_mention", range.first, length, user = source.user) is TextMentionTextSource -> RawMessageEntity("text_mention", offset, length, user = user)
is UnderlineTextSource -> RawMessageEntity("underline", range.first, length) is UnderlineTextSource -> RawMessageEntity("underline", offset, length)
is StrikethroughTextSource -> RawMessageEntity("strikethrough", range.first, length) is StrikethroughTextSource -> RawMessageEntity("strikethrough", offset, length)
else -> null else -> null
} }
) + if (source is MultilevelTextSource) { ) + if (this is MultilevelTextSource) {
source.textParts(range.first).asRawMessageEntities() subsources.toRawMessageEntities(offset)
} else { } else {
emptyList() emptyList()
} }
} }
internal fun List<TextPart>.asRawMessageEntities(): List<RawMessageEntity> = flatMap { it.asRawMessageEntities() }
internal fun List<TextSource>.toTextParts(preOffset: Int = 0): List<TextPart> { internal fun List<TextSource>.toRawMessageEntities(preOffset: Int = 0): List<RawMessageEntity> {
var i = preOffset var i = preOffset
return map { return flatMap { textSource ->
TextPart( textSource.toRawMessageEntities(i).also {
i until (i + it.source.length), i += it.maxByOrNull { it.length } ?.length ?: textSource.source.length
it
).also {
i = it.range.last + 1
} }
} }
} }
@ -136,10 +175,8 @@ fun String.removeLeading(word: String) = if (startsWith(word)){
this this
} }
internal fun List<TextSource>.toRawMessageEntities(): List<RawMessageEntity> = toTextParts().asRawMessageEntities() internal fun List<TextSource>.toRawMessageEntities(): List<RawMessageEntity> = toRawMessageEntities(0)
internal fun RawMessageEntities.asTextParts(sourceString: String): List<TextPart> = sourceString.fullListOfSubSource( internal fun RawMessageEntities.asTextSources(sourceString: String): List<TextSource> = createTextSources(sourceString, this).fillWithRegulars(sourceString)
createTextPart(sourceString, this)
)
internal typealias RawMessageEntities = List<RawMessageEntity> internal typealias RawMessageEntities = List<RawMessageEntity>

View File

@ -3,7 +3,6 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
/** /**

View File

@ -2,14 +2,13 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer
import dev.inmo.tgbotapi.CommonAbstracts.TextSource import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.justTextSources import dev.inmo.tgbotapi.types.MessageEntity.RawMessageEntity
import dev.inmo.tgbotapi.types.MessageEntity.* import dev.inmo.tgbotapi.types.MessageEntity.asTextSources
import dev.inmo.tgbotapi.types.MessageEntity.RawMessageEntities import kotlinx.serialization.KSerializer
import dev.inmo.tgbotapi.utils.RiskFeature import kotlinx.serialization.Serializer
import kotlinx.serialization.* import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.*
private val baseSerializers: Map<String, KSerializer<out TextSource>> = mapOf( private val baseSerializers: Map<String, KSerializer<out TextSource>> = mapOf(
"regular" to RegularTextSource.serializer(), "regular" to RegularTextSource.serializer(),

View File

@ -26,6 +26,8 @@ internal object BotActionSerializer: KSerializer<BotAction> {
UploadVideoAction.actionName -> UploadVideoAction UploadVideoAction.actionName -> UploadVideoAction
RecordAudioAction.actionName -> RecordAudioAction RecordAudioAction.actionName -> RecordAudioAction
UploadAudioAction.actionName -> UploadAudioAction UploadAudioAction.actionName -> UploadAudioAction
RecordVoiceAction.actionName -> RecordVoiceAction
UploadVoiceAction.actionName -> UploadVoiceAction
UploadDocumentAction.actionName -> UploadDocumentAction UploadDocumentAction.actionName -> UploadDocumentAction
FindLocationAction.actionName -> FindLocationAction FindLocationAction.actionName -> FindLocationAction
RecordVideoNoteAction.actionName -> RecordVideoNoteAction RecordVideoNoteAction.actionName -> RecordVideoNoteAction
@ -83,24 +85,70 @@ inline fun BotAction.asUploadVideo() = this as? UploadVideoAction
* Will notify user that bot is recording some audio * Will notify user that bot is recording some audio
*/ */
@Serializable(BotActionSerializer::class) @Serializable(BotActionSerializer::class)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("RecordVoiceAction", "dev.inmo.tgbotapi.types.actions.RecordVoiceAction")
)
object RecordAudioAction : BotAction() { object RecordAudioAction : BotAction() {
override val actionName: String = "record_audio" override val actionName: String = "record_audio"
} }
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("recordVoice", "dev.inmo.tgbotapi.types.actions.recordVoice")
)
inline val recordAudio inline val recordAudio
get() = RecordAudioAction get() = RecordAudioAction
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("asRecordVoice", "dev.inmo.tgbotapi.types.actions.asRecordVoice")
)
inline fun BotAction.asRecordAudio() = this as? RecordAudioAction inline fun BotAction.asRecordAudio() = this as? RecordAudioAction
/** /**
* Will notify user that bot is uploading some audio * Will notify user that bot is uploading some audio
*/ */
@Serializable(BotActionSerializer::class) @Serializable(BotActionSerializer::class)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("UploadVoiceAction", "dev.inmo.tgbotapi.types.actions.UploadVoiceAction")
)
object UploadAudioAction : BotAction() { object UploadAudioAction : BotAction() {
override val actionName: String = "upload_audio" override val actionName: String = "upload_audio"
} }
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("uploadVoice", "dev.inmo.tgbotapi.types.actions.uploadVoice")
)
inline val uploadAudio inline val uploadAudio
get() = UploadAudioAction get() = UploadAudioAction
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("asUploadVoice", "dev.inmo.tgbotapi.types.actions.asUploadVoice")
)
inline fun BotAction.asUploadAudio() = this as? UploadAudioAction inline fun BotAction.asUploadAudio() = this as? UploadAudioAction
/**
* Will notify user that bot is recording some audio
*/
@Serializable(BotActionSerializer::class)
object RecordVoiceAction : BotAction() {
override val actionName: String = "record_voice"
}
inline val recordVoice
get() = RecordVoiceAction
inline fun BotAction.asRecordVoice() = this as? RecordVoiceAction
/**
* Will notify user that bot is uploading some audio
*/
@Serializable(BotActionSerializer::class)
object UploadVoiceAction : BotAction() {
override val actionName: String = "upload_voice"
}
inline val uploadVoice
get() = UploadVoiceAction
inline fun BotAction.asUploadVoice() = this as? UploadVoiceAction
/** /**
* Will notify user that bot is uploading some document * Will notify user that bot is uploading some document
*/ */

View File

@ -21,7 +21,7 @@ data class InlineKeyboardMarkup(
// first button is not PayInlineKeyboardButton // first button is not PayInlineKeyboardButton
val firstIsPaymentButton = keyboard.first().firstOrNull() is PayInlineKeyboardButton val firstIsPaymentButton = keyboard.first().firstOrNull() is PayInlineKeyboardButton
if (!firstIsPaymentButton) { if (!firstIsPaymentButton) {
error("In case if PayInlineKeyboardButton included in keyboard - it must ") error("In case if PayInlineKeyboardButton included in keyboard - it must be the first one")
} }
} }
} }

View File

@ -4,10 +4,10 @@ import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.abstracts.Chat import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import dev.inmo.tgbotapi.types.chat.abstracts.UnknownChatType import dev.inmo.tgbotapi.types.chat.abstracts.UnknownChatType
import dev.inmo.tgbotapi.types.chat.abstracts.extended.ExtendedChat import dev.inmo.tgbotapi.types.chat.abstracts.extended.ExtendedChat
import dev.inmo.tgbotapi.types.chat.abstracts.extended.UnknownExtendedChat
import dev.inmo.tgbotapi.types.chat.extended.* import dev.inmo.tgbotapi.types.chat.extended.*
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.* import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
@ -17,6 +17,40 @@ import kotlinx.serialization.json.*
private val formatter private val formatter
get() = nonstrictJsonFormat get() = nonstrictJsonFormat
@Serializable(ChatTypeSerializer::class)
sealed class ChatType {
abstract val stringified: String
@Serializable(ChatTypeSerializer::class)
object PrivateChatType : ChatType() { override val stringified = "private" }
@Serializable(ChatTypeSerializer::class)
object GroupChatType : ChatType() { override val stringified = "group" }
@Serializable(ChatTypeSerializer::class)
object SupergroupChatType : ChatType() { override val stringified = "supergroup" }
@Serializable(ChatTypeSerializer::class)
object ChannelChatType : ChatType() { override val stringified = "channel" }
@Serializable(ChatTypeSerializer::class)
class UnknownChatType(override val stringified: String) : ChatType()
}
val String.asChatType
get() = when (this) {
ChatType.PrivateChatType.stringified -> ChatType.PrivateChatType
ChatType.GroupChatType.stringified -> ChatType.GroupChatType
ChatType.SupergroupChatType.stringified -> ChatType.SupergroupChatType
ChatType.ChannelChatType.stringified -> ChatType.ChannelChatType
else -> ChatType.UnknownChatType(this)
}
@Serializer(ChatType::class)
object ChatTypeSerializer : KSerializer<ChatType> {
override val descriptor: SerialDescriptor = String.serializer().descriptor
override fun deserialize(decoder: Decoder): ChatType {
return decoder.decodeString().asChatType
}
override fun serialize(encoder: Encoder, value: ChatType) {
encoder.encodeString(value.stringified)
}
}
internal object PreviewChatSerializer : KSerializer<Chat> { internal object PreviewChatSerializer : KSerializer<Chat> {
@InternalSerializationApi @InternalSerializationApi
override val descriptor: SerialDescriptor = buildSerialDescriptor("PreviewChatSerializer", PolymorphicKind.OPEN) override val descriptor: SerialDescriptor = buildSerialDescriptor("PreviewChatSerializer", PolymorphicKind.OPEN)
@ -24,14 +58,14 @@ internal object PreviewChatSerializer : KSerializer<Chat> {
override fun deserialize(decoder: Decoder): Chat { override fun deserialize(decoder: Decoder): Chat {
val decodedJson = JsonObject.serializer().deserialize(decoder) val decodedJson = JsonObject.serializer().deserialize(decoder)
val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?: error("Field $typeField must be presented, but absent in $decodedJson") val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?.asChatType ?: error("Field $typeField must be presented, but absent in $decodedJson")
return when (type) { return when (type) {
"private" -> formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson) ChatType.PrivateChatType -> formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson)
"group" -> formatter.decodeFromJsonElement(GroupChatImpl.serializer(), decodedJson) ChatType.GroupChatType -> formatter.decodeFromJsonElement(GroupChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.decodeFromJsonElement(SupergroupChatImpl.serializer(), decodedJson) ChatType.SupergroupChatType -> formatter.decodeFromJsonElement(SupergroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.decodeFromJsonElement(ChannelChatImpl.serializer(), decodedJson) ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ChannelChatImpl.serializer(), decodedJson)
else -> UnknownChatType( is ChatType.UnknownChatType -> UnknownChatType(
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(), formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(),
decodedJson.toString() decodedJson.toString()
) )
@ -56,14 +90,18 @@ internal object ExtendedChatSerializer : KSerializer<ExtendedChat> {
override fun deserialize(decoder: Decoder): ExtendedChat { override fun deserialize(decoder: Decoder): ExtendedChat {
val decodedJson = JsonObject.serializer().deserialize(decoder) val decodedJson = JsonObject.serializer().deserialize(decoder)
val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?: error("Field $typeField must be presented, but absent in $decodedJson") val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?.asChatType ?: error("Field $typeField must be presented, but absent in $decodedJson")
return when (type) { return when (type) {
"private" -> formatter.decodeFromJsonElement(ExtendedPrivateChatImpl.serializer(), decodedJson) // else -> throw IllegalArgumentException("Unknown type of chat")
"group" -> formatter.decodeFromJsonElement(ExtendedGroupChatImpl.serializer(), decodedJson) ChatType.PrivateChatType -> formatter.decodeFromJsonElement(ExtendedPrivateChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.decodeFromJsonElement(ExtendedSupergroupChatImpl.serializer(), decodedJson) ChatType.GroupChatType -> formatter.decodeFromJsonElement(ExtendedGroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.decodeFromJsonElement(ExtendedChannelChatImpl.serializer(), decodedJson) ChatType.SupergroupChatType -> formatter.decodeFromJsonElement(ExtendedSupergroupChatImpl.serializer(), decodedJson)
else -> throw IllegalArgumentException("Unknown type of chat") ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ExtendedChannelChatImpl.serializer(), decodedJson)
is ChatType.UnknownChatType -> UnknownExtendedChat(
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(),
decodedJson.toString()
)
} }
} }

View File

@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types.chat.abstracts.extended package dev.inmo.tgbotapi.types.chat.abstracts.extended
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.ChatPhoto import dev.inmo.tgbotapi.types.ChatPhoto
import dev.inmo.tgbotapi.types.chat.ExtendedChatSerializer import dev.inmo.tgbotapi.types.chat.ExtendedChatSerializer
import dev.inmo.tgbotapi.types.chat.abstracts.Chat import dev.inmo.tgbotapi.types.chat.abstracts.Chat
@ -8,4 +9,11 @@ import kotlinx.serialization.Serializable
@Serializable(ExtendedChatSerializer::class) @Serializable(ExtendedChatSerializer::class)
interface ExtendedChat : Chat { interface ExtendedChat : Chat {
val chatPhoto: ChatPhoto? val chatPhoto: ChatPhoto?
} }
data class UnknownExtendedChat(
override val id: ChatId,
val raw: String
) : ExtendedChat {
override val chatPhoto: ChatPhoto? = null
}

View File

@ -34,11 +34,11 @@ data class VideoFile(
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun VideoFile.toInputMediaVideo( inline fun VideoFile.toInputMediaVideo(
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null parseMode: ParseMode? = null
) = InputMediaVideo( ) = InputMediaVideo(
fileId, fileId,
caption, text,
parseMode, parseMode,
width, width,
height, height,

View File

@ -8,7 +8,7 @@ data class Game(
override val title: String, override val title: String,
val description: String, val description: String,
val photo: Photo, val photo: Photo,
override val caption: String? = null, override val text: String? = null,
override val captionEntities: List<TextPart> = emptyList(), override val textSources: TextSourcesList = emptyList(),
val animation: AnimationFile? = null val animation: AnimationFile? = null
) : Titled, CaptionedInput ) : Titled, CaptionedInput, TextedInput

View File

@ -2,7 +2,7 @@ package dev.inmo.tgbotapi.types.games
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.RawMessageEntities import dev.inmo.tgbotapi.types.MessageEntity.RawMessageEntities
import dev.inmo.tgbotapi.types.MessageEntity.asTextParts import dev.inmo.tgbotapi.types.MessageEntity.asTextSources
import dev.inmo.tgbotapi.types.files.* import dev.inmo.tgbotapi.types.files.*
import kotlinx.serialization.* import kotlinx.serialization.*
@ -16,9 +16,9 @@ internal data class RawGame(
@SerialName(photoField) @SerialName(photoField)
private val photo: Photo, private val photo: Photo,
@SerialName(textField) @SerialName(textField)
private val caption: String? = null, private val text: String? = null,
@SerialName(textEntitiesField) @SerialName(textEntitiesField)
private val captionEntities: RawMessageEntities = emptyList(), private val textEntities: RawMessageEntities = emptyList(),
@SerialName(animationField) @SerialName(animationField)
private val animation: AnimationFile? = null private val animation: AnimationFile? = null
) { ) {
@ -27,8 +27,8 @@ internal data class RawGame(
title, title,
description, description,
photo, photo,
caption, text,
caption ?.let { _ -> captionEntities.asTextParts(caption) } ?: emptyList(), text ?.let { _ -> textEntities.asTextSources(text) } ?: emptyList(),
animation animation
) )
} }

View File

@ -1,3 +1,3 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.abstracts package dev.inmo.tgbotapi.types.message.ChatEvents.abstracts
interface VoiceChatEvent : SupergroupEvent interface VoiceChatEvent : CommonEvent

View File

@ -0,0 +1,13 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.voice
import dev.inmo.tgbotapi.types.TelegramDate
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.VoiceChatEvent
import dev.inmo.tgbotapi.types.startDateField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class VoiceChatScheduled(
@SerialName(startDateField)
val startDate: TelegramDate
) : VoiceChatEvent

View File

@ -2,7 +2,7 @@ package dev.inmo.tgbotapi.types.message
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.RawMessageEntities import dev.inmo.tgbotapi.types.MessageEntity.RawMessageEntities
import dev.inmo.tgbotapi.types.MessageEntity.asTextParts import dev.inmo.tgbotapi.types.MessageEntity.asTextSources
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.abstracts.* import dev.inmo.tgbotapi.types.chat.abstracts.*
import dev.inmo.tgbotapi.types.dice.Dice import dev.inmo.tgbotapi.types.dice.Dice
@ -83,6 +83,7 @@ internal data class RawMessage(
private val successful_payment: SuccessfulPayment? = null, private val successful_payment: SuccessfulPayment? = null,
// Voice Chat Service Messages // Voice Chat Service Messages
private val voice_chat_scheduled: VoiceChatScheduled? = null,
private val voice_chat_started: VoiceChatStarted? = null, private val voice_chat_started: VoiceChatStarted? = null,
private val voice_chat_ended: VoiceChatEnded? = null, private val voice_chat_ended: VoiceChatEnded? = null,
private val voice_chat_participants_invited: VoiceChatParticipantsInvited? = null, private val voice_chat_participants_invited: VoiceChatParticipantsInvited? = null,
@ -101,11 +102,11 @@ internal data class RawMessage(
) { ) {
private val content: MessageContent? by lazy { private val content: MessageContent? by lazy {
val adaptedCaptionEntities = caption ?.let { val adaptedCaptionEntities = caption ?.let {
(caption_entities ?: emptyList()).asTextParts(caption) (caption_entities ?: emptyList()).asTextSources(caption)
} ?: emptyList() } ?: emptyList()
when { when {
text != null -> TextContent(text, (entities ?: emptyList()).asTextParts(text)) text != null -> TextContent(text, (entities ?: emptyList()).asTextSources(text))
audio != null -> AudioContent( audio != null -> AudioContent(
audio, audio,
caption, caption,
@ -182,6 +183,7 @@ internal data class RawMessage(
new_chat_title != null -> NewChatTitle(new_chat_title) new_chat_title != null -> NewChatTitle(new_chat_title)
new_chat_photo != null -> NewChatPhoto(new_chat_photo.toList()) new_chat_photo != null -> NewChatPhoto(new_chat_photo.toList())
voice_chat_started != null -> voice_chat_started voice_chat_started != null -> voice_chat_started
voice_chat_scheduled != null -> voice_chat_scheduled
message_auto_delete_timer_changed != null -> message_auto_delete_timer_changed message_auto_delete_timer_changed != null -> message_auto_delete_timer_changed
voice_chat_ended != null -> voice_chat_ended voice_chat_ended != null -> voice_chat_ended
voice_chat_participants_invited != null -> voice_chat_participants_invited voice_chat_participants_invited != null -> voice_chat_participants_invited

View File

@ -1,19 +1,18 @@
package dev.inmo.tgbotapi.types.message.content package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.TextedInput
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.SendTextMessage import dev.inmo.tgbotapi.requests.send.SendTextMessage
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.MessageIdentifier import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.defaultParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
data class TextContent( data class TextContent(
override val text: String, override val text: String,
override val textEntities: List<TextPart> = emptyList() override val textSources: TextSourcesList = emptyList(),
) : MessageContent, TextedInput { ) : MessageContent, TextedInput {
override fun createResend( override fun createResend(
chatId: ChatIdentifier, chatId: ChatIdentifier,

View File

@ -1,9 +1,10 @@
package dev.inmo.tgbotapi.types.message.content.abstracts package dev.inmo.tgbotapi.types.message.content.abstracts
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextedInput
import dev.inmo.tgbotapi.types.InputMedia.* import dev.inmo.tgbotapi.types.InputMedia.*
interface MediaGroupContent : MediaContent, CaptionedInput { interface MediaGroupContent : MediaContent, CaptionedInput, TextedInput {
fun toMediaGroupMemberInputMedia(): MediaGroupMemberInputMedia fun toMediaGroupMemberInputMedia(): MediaGroupMemberInputMedia
} }

View File

@ -15,9 +15,9 @@ import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
data class AnimationContent( data class AnimationContent(
override val media: AnimationFile, override val media: AnimationFile,
val includedDocument: DocumentFile?, val includedDocument: DocumentFile?,
override val caption: String?, override val text: String?,
override val captionEntities: List<TextPart> override val textSources: TextSourcesList = emptyList()
) : MediaContent, CaptionedInput { ) : MediaContent, CaptionedInput, TextedInput {
override fun createResend( override fun createResend(
chatId: ChatIdentifier, chatId: ChatIdentifier,
disableNotification: Boolean, disableNotification: Boolean,

View File

@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.types.message.content.media package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendAudio import dev.inmo.tgbotapi.requests.send.media.SendAudio
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
@ -15,8 +14,8 @@ import dev.inmo.tgbotapi.types.message.content.abstracts.AudioMediaGroupContent
data class AudioContent( data class AudioContent(
override val media: AudioFile, override val media: AudioFile,
override val caption: String? = null, override val text: String? = null,
override val captionEntities: List<TextPart> = emptyList() override val textSources: TextSourcesList = emptyList()
) : AudioMediaGroupContent { ) : AudioMediaGroupContent {
override fun createResend( override fun createResend(
chatId: ChatIdentifier, chatId: ChatIdentifier,

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.message.content.media package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.TextedInput
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendDocument import dev.inmo.tgbotapi.requests.send.media.SendDocument
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
@ -16,8 +17,8 @@ import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
data class DocumentContent( data class DocumentContent(
override val media: DocumentFile, override val media: DocumentFile,
override val caption: String? = null, override val text: String? = null,
override val captionEntities: List<TextPart> = emptyList() override val textSources: TextSourcesList = emptyList()
) : DocumentMediaGroupContent { ) : DocumentMediaGroupContent {
override fun createResend( override fun createResend(
chatId: ChatIdentifier, chatId: ChatIdentifier,
@ -43,10 +44,10 @@ data class DocumentContent(
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun MediaContent.asDocumentContent() = when (this) { inline fun MediaContent.asDocumentContent() = when (this) {
is CaptionedInput -> DocumentContent( is TextedInput -> DocumentContent(
media.asDocumentFile(), media.asDocumentFile(),
caption, text,
captionEntities textSources
) )
else -> DocumentContent( else -> DocumentContent(
media.asDocumentFile() media.asDocumentFile()

View File

@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.types.message.content.media package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendPhoto import dev.inmo.tgbotapi.requests.send.media.SendPhoto
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
@ -16,8 +15,8 @@ import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
data class PhotoContent( data class PhotoContent(
override val mediaCollection: Photo, override val mediaCollection: Photo,
override val caption: String? = null, override val text: String? = null,
override val captionEntities: List<TextPart> = emptyList() override val textSources: TextSourcesList = emptyList()
) : MediaCollectionContent<PhotoSize>, VisualMediaGroupContent { ) : MediaCollectionContent<PhotoSize>, VisualMediaGroupContent {
override val media: PhotoSize = mediaCollection.biggest() ?: throw IllegalStateException("Can't locate any photo size for this content") override val media: PhotoSize = mediaCollection.biggest() ?: throw IllegalStateException("Can't locate any photo size for this content")

View File

@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.types.message.content.media package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendVideo import dev.inmo.tgbotapi.requests.send.media.SendVideo
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
@ -15,8 +14,8 @@ import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
data class VideoContent( data class VideoContent(
override val media: VideoFile, override val media: VideoFile,
override val caption: String? = null, override val text: String? = null,
override val captionEntities: List<TextPart> = emptyList() override val textSources: TextSourcesList = emptyList()
) : VisualMediaGroupContent { ) : VisualMediaGroupContent {
override fun createResend( override fun createResend(
chatId: ChatIdentifier, chatId: ChatIdentifier,

View File

@ -13,9 +13,9 @@ import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
data class VoiceContent( data class VoiceContent(
override val media: VoiceFile, override val media: VoiceFile,
override val caption: String? = null, override val text: String? = null,
override val captionEntities: List<TextPart> = emptyList() override val textSources: TextSourcesList = emptyList()
) : MediaContent, CaptionedInput { ) : MediaContent, CaptionedInput, TextedInput {
override fun createResend( override fun createResend(
chatId: ChatIdentifier, chatId: ChatIdentifier,
disableNotification: Boolean, disableNotification: Boolean,

View File

@ -3,7 +3,7 @@ package dev.inmo.tgbotapi.types.polls
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import com.soywiz.klock.TimeSpan import com.soywiz.klock.TimeSpan
import dev.inmo.tgbotapi.CommonAbstracts.ExplainedInput import dev.inmo.tgbotapi.CommonAbstracts.ExplainedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.* import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
@ -135,8 +135,8 @@ data class QuizPoll(
* Nullable due to documentation (https://core.telegram.org/bots/api#poll) * Nullable due to documentation (https://core.telegram.org/bots/api#poll)
*/ */
val correctOptionId: Int? = null, val correctOptionId: Int? = null,
override val explanation: String? = null, override val text: String? = null,
override val explanationEntities: List<TextPart> = emptyList(), override val textSources: List<TextSource> = emptyList(),
override val isClosed: Boolean = false, override val isClosed: Boolean = false,
override val isAnonymous: Boolean = false, override val isAnonymous: Boolean = false,
override val scheduledCloseInfo: ScheduledCloseInfo? = null override val scheduledCloseInfo: ScheduledCloseInfo? = null
@ -159,7 +159,7 @@ internal object PollSerializer : KSerializer<Poll> {
rawPoll.votesCount, rawPoll.votesCount,
rawPoll.correctOptionId, rawPoll.correctOptionId,
rawPoll.explanation, rawPoll.explanation,
rawPoll.explanation?.let { rawPoll.explanationEntities.asTextParts(it) } ?: emptyList(), rawPoll.explanation?.let { rawPoll.explanationEntities.asTextSources(it) } ?: emptyList(),
rawPoll.isClosed, rawPoll.isClosed,
rawPoll.isAnonymous, rawPoll.isAnonymous,
rawPoll.scheduledCloseInfo rawPoll.scheduledCloseInfo
@ -210,8 +210,8 @@ internal object PollSerializer : KSerializer<Poll> {
value.isAnonymous, value.isAnonymous,
regularPollType, regularPollType,
correctOptionId = value.correctOptionId, correctOptionId = value.correctOptionId,
explanation = value.explanation, explanation = value.text,
explanationEntities = value.explanationEntities.asRawMessageEntities(), explanationEntities = value.textSources.toRawMessageEntities(),
openPeriod = (closeInfo as? ApproximateScheduledCloseInfo) ?.openDuration ?.seconds ?.toLong(), openPeriod = (closeInfo as? ApproximateScheduledCloseInfo) ?.openDuration ?.seconds ?.toLong(),
closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L) closeDate = (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000L)
) )

View File

@ -1,77 +1,12 @@
package dev.inmo.tgbotapi.utils.internal package dev.inmo.tgbotapi.utils.internal
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.MultilevelTextSource
import dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.types.UserId import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.link import dev.inmo.tgbotapi.types.link
import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Link import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Link
import dev.inmo.tgbotapi.utils.extensions.toHtml import dev.inmo.tgbotapi.utils.extensions.toHtml
internal fun String.fullListOfSubSource(sourceList: List<TextPart>): List<TextPart> {
val sortedSourceList = sourceList.sortedBy { it.range.first }.toMutableList()
var previousLastIndex = 0
val newSubSources = mutableListOf<TextPart>()
while (sortedSourceList.isNotEmpty()) {
val topSource = sortedSourceList.removeAt(0)
if (topSource.range.first - previousLastIndex > 0) {
val range = previousLastIndex until topSource.range.first
newSubSources.add(
TextPart(
range,
RegularTextSource(
substring(range)
)
)
)
}
newSubSources.add(topSource)
previousLastIndex = topSource.range.last + 1
}
if (length > previousLastIndex) {
val range = previousLastIndex until length
newSubSources.add(
TextPart(
range,
RegularTextSource(
substring(range)
)
)
)
}
return newSubSources
}
internal fun List<TextPart>.shiftSourcesToTheLeft(shiftCount: Int = 1): List<TextPart> {
return mapNotNull {
val first = (it.range.first - shiftCount).let { firstCalculated ->
if (firstCalculated < 0) {
0
} else {
firstCalculated
}
}
val last = (it.range.last - shiftCount).let { lastCalculated ->
if (lastCalculated < 0) {
0
} else {
lastCalculated
}
}
it.copy(range = first .. last).let { newSubSource ->
if (newSubSource.range.isEmpty()) {
null
} else {
newSubSource
}
}
}
}
private fun List<TextSource>.joinSubSourcesMarkdownV2() = joinToString("") { private fun List<TextSource>.joinSubSourcesMarkdownV2() = joinToString("") {
it.markdownV2 it.markdownV2
} }

View File

@ -22,6 +22,8 @@ class BotActionTests {
UploadVideoAction -> example.botAction.actionName UploadVideoAction -> example.botAction.actionName
RecordAudioAction -> example.botAction.actionName RecordAudioAction -> example.botAction.actionName
UploadAudioAction -> example.botAction.actionName UploadAudioAction -> example.botAction.actionName
RecordVoiceAction -> example.botAction.actionName
UploadVoiceAction -> example.botAction.actionName
UploadDocumentAction -> example.botAction.actionName UploadDocumentAction -> example.botAction.actionName
FindLocationAction -> example.botAction.actionName FindLocationAction -> example.botAction.actionName
RecordVideoNoteAction -> example.botAction.actionName RecordVideoNoteAction -> example.botAction.actionName
@ -51,6 +53,8 @@ class BotActionTests {
UploadVideoAction.example(), UploadVideoAction.example(),
RecordAudioAction.example(), RecordAudioAction.example(),
UploadAudioAction.example(), UploadAudioAction.example(),
RecordVoiceAction.example(),
UploadVoiceAction.example(),
UploadDocumentAction.example(), UploadDocumentAction.example(),
FindLocationAction.example(), FindLocationAction.example(),
RecordVideoNoteAction.example(), RecordVideoNoteAction.example(),

View File

@ -1,6 +1,6 @@
package dev.inmo.tgbotapi.types.MessageEntity package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.TextPart import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.types.MessageEntity.textsources.* import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -36,19 +36,19 @@ internal val testTextEntities = listOf(
RawMessageEntity( RawMessageEntity(
"mention", "mention",
39, 39,
6 8
) )
) )
fun List<TextPart>.testTextParts() { fun List<TextSource>.testTextSources() {
assertTrue (first().source is RegularTextSource) assertTrue (first() is RegularTextSource)
assertTrue (get(1).source is BoldTextSource) assertTrue (get(1) is BoldTextSource)
assertTrue (get(2).source is RegularTextSource) assertTrue (get(2) is RegularTextSource)
assertTrue (get(3).source is HashTagTextSource) assertTrue (get(3) is HashTagTextSource)
assertTrue (get(4).source is RegularTextSource) assertTrue (get(4) is RegularTextSource)
assertTrue (get(5).source is MentionTextSource) assertTrue (get(5) is MentionTextSource)
val boldSource = get(1).source as BoldTextSource val boldSource = get(1) as BoldTextSource
assertTrue (boldSource.subsources.first() is ItalicTextSource) assertTrue (boldSource.subsources.first() is ItalicTextSource)
assertTrue (boldSource.subsources[1] is RegularTextSource) assertTrue (boldSource.subsources[1] is RegularTextSource)
assertTrue (boldSource.subsources[2] is StrikethroughTextSource) assertTrue (boldSource.subsources[2] is StrikethroughTextSource)

View File

@ -48,7 +48,7 @@ class StringFormattingTests {
hashtag("tag") + hashtag("tag") +
" and " + " and " +
mention("mention") mention("mention")
sources.toTextParts().testTextParts() sources.testTextSources()
assertEquals(formattedV2Text, sources.toMarkdownV2Texts().first()) assertEquals(formattedV2Text, sources.toMarkdownV2Texts().first())
assertEquals(formattedHtmlText, sources.toHtmlTexts().first()) assertEquals(formattedHtmlText, sources.toHtmlTexts().first())

View File

@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.MessageEntity package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.justTextSources
import dev.inmo.tgbotapi.extensions.utils.formatting.toHtmlTexts import dev.inmo.tgbotapi.extensions.utils.formatting.toHtmlTexts
import dev.inmo.tgbotapi.extensions.utils.formatting.toMarkdownV2Texts import dev.inmo.tgbotapi.extensions.utils.formatting.toMarkdownV2Texts
import kotlin.test.Test import kotlin.test.Test
@ -9,23 +8,23 @@ import kotlin.test.assertEquals
class TextPartsCreatingTests { class TextPartsCreatingTests {
@Test @Test
fun testThatTextWithMultilevelPartsCorrectlyCreating() { fun testThatTextWithMultilevelPartsCorrectlyCreating() {
val textParts = testTextEntities.asTextParts(testText) val textSources = testTextEntities.asTextSources(testText)
textParts.testTextParts() textSources.testTextSources()
assertEquals( assertEquals(
formattedV2Text, formattedV2Text,
textParts.justTextSources().toMarkdownV2Texts().first() textSources.toMarkdownV2Texts().first()
) )
} }
@Test @Test
fun testThatTextWithMultilevelPartsCorrectlyCreatingInHtml() { fun testThatTextWithMultilevelPartsCorrectlyCreatingInHtml() {
val textParts = testTextEntities.asTextParts(testText) val textSources = testTextEntities.asTextSources(testText)
textParts.testTextParts() textSources.testTextSources()
assertEquals( assertEquals(
formattedHtmlText, formattedHtmlText,
textParts.justTextSources().toHtmlTexts().first() textSources.toHtmlTexts().first()
) )
} }
} }

View File

@ -4,10 +4,7 @@ import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.makeString import dev.inmo.tgbotapi.CommonAbstracts.makeString
import dev.inmo.tgbotapi.TestsJsonFormat import dev.inmo.tgbotapi.TestsJsonFormat
import dev.inmo.tgbotapi.extensions.utils.formatting.* import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourceSerializer
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.encodeToString
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.extensions.api.edit.caption package dev.inmo.tgbotapi.extensions.api.edit.caption
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.edit.caption.EditChatMessageCaption import dev.inmo.tgbotapi.requests.edit.caption.EditChatMessageCaption
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
@ -35,7 +34,7 @@ suspend fun <T> TelegramBot.editMessageCaption(
text: String, text: String,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<MediaContent> where T : CaptionedInput, T : MediaContent { ): ContentMessage<MediaContent> where T : TextedWithTextSources, T : MediaContent {
return editMessageCaption(message.chat.id, message.messageId, text, parseMode, replyMarkup) return editMessageCaption(message.chat.id, message.messageId, text, parseMode, replyMarkup)
} }
@ -59,6 +58,6 @@ suspend fun <T> TelegramBot.editMessageCaption(
message: ContentMessage<T>, message: ContentMessage<T>,
entities: List<TextSource>, entities: List<TextSource>,
replyMarkup: InlineKeyboardMarkup? = null replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<MediaContent> where T : CaptionedInput, T : MediaContent { ): ContentMessage<MediaContent> where T : TextedWithTextSources, T : MediaContent {
return editMessageCaption(message.chat.id, message.messageId, entities, replyMarkup) return editMessageCaption(message.chat.id, message.messageId, entities, replyMarkup)
} }

View File

@ -2,7 +2,8 @@ package dev.inmo.tgbotapi.extensions.api.passport
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.SetPassportDataErrors import dev.inmo.tgbotapi.requests.SetPassportDataErrors
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.message.PassportMessage import dev.inmo.tgbotapi.types.message.PassportMessage
import dev.inmo.tgbotapi.types.passport.PassportData import dev.inmo.tgbotapi.types.passport.PassportData
import dev.inmo.tgbotapi.types.passport.PassportElementError import dev.inmo.tgbotapi.types.passport.PassportElementError

View File

@ -35,14 +35,30 @@ suspend fun TelegramBot.sendActionUploadVideo(
chatId: ChatIdentifier chatId: ChatIdentifier
) = sendBotAction(chatId, UploadVideoAction) ) = sendBotAction(chatId, UploadVideoAction)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("sendActionRecordVoice", "dev.inmo.tgbotapi.extensions.api.send.sendActionRecordVoice")
)
suspend fun TelegramBot.sendActionRecordAudio( suspend fun TelegramBot.sendActionRecordAudio(
chatId: ChatIdentifier chatId: ChatIdentifier
) = sendBotAction(chatId, RecordAudioAction) ) = sendBotAction(chatId, RecordAudioAction)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("sendActionUploadVoice", "dev.inmo.tgbotapi.extensions.api.send.sendActionUploadVoice")
)
suspend fun TelegramBot.sendActionUploadAudio( suspend fun TelegramBot.sendActionUploadAudio(
chatId: ChatIdentifier chatId: ChatIdentifier
) = sendBotAction(chatId, UploadAudioAction) ) = sendBotAction(chatId, UploadAudioAction)
suspend fun TelegramBot.sendActionRecordVoice(
chatId: ChatIdentifier
) = sendBotAction(chatId, RecordVoiceAction)
suspend fun TelegramBot.sendActionUploadVoice(
chatId: ChatIdentifier
) = sendBotAction(chatId, UploadVoiceAction)
suspend fun TelegramBot.sendActionUploadDocument( suspend fun TelegramBot.sendActionUploadDocument(
chatId: ChatIdentifier chatId: ChatIdentifier
) = sendBotAction(chatId, UploadDocumentAction) ) = sendBotAction(chatId, UploadDocumentAction)
@ -76,14 +92,30 @@ suspend fun TelegramBot.sendActionUploadVideo(
chat: Chat chat: Chat
) = sendBotAction(chat, UploadVideoAction) ) = sendBotAction(chat, UploadVideoAction)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("sendActionRecordVoice", "dev.inmo.tgbotapi.extensions.api.send.sendActionRecordVoice")
)
suspend fun TelegramBot.sendActionRecordAudio( suspend fun TelegramBot.sendActionRecordAudio(
chat: Chat chat: Chat
) = sendBotAction(chat, RecordAudioAction) ) = sendBotAction(chat, RecordAudioAction)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("sendActionUploadVoice", "dev.inmo.tgbotapi.extensions.api.send.sendActionUploadVoice")
)
suspend fun TelegramBot.sendActionUploadAudio( suspend fun TelegramBot.sendActionUploadAudio(
chat: Chat chat: Chat
) = sendBotAction(chat, UploadAudioAction) ) = sendBotAction(chat, UploadAudioAction)
suspend fun TelegramBot.sendActionRecordVoice(
chat: Chat
) = sendBotAction(chat, RecordVoiceAction)
suspend fun TelegramBot.sendActionUploadVoice(
chat: Chat
) = sendBotAction(chat, UploadVoiceAction)
suspend fun TelegramBot.sendActionUploadDocument( suspend fun TelegramBot.sendActionUploadDocument(
chat: Chat chat: Chat
) = sendBotAction(chat, UploadDocumentAction) ) = sendBotAction(chat, UploadDocumentAction)

View File

@ -56,8 +56,18 @@ suspend fun <T> TelegramBot.withTypingAction(chatId: ChatId, block: TelegramBotA
suspend fun <T> TelegramBot.withUploadPhotoAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadPhotoAction, block) suspend fun <T> TelegramBot.withUploadPhotoAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadPhotoAction, block)
suspend fun <T> TelegramBot.withRecordVideoAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordVideoAction, block) suspend fun <T> TelegramBot.withRecordVideoAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordVideoAction, block)
suspend fun <T> TelegramBot.withUploadVideoAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadVideoAction, block) suspend fun <T> TelegramBot.withUploadVideoAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadVideoAction, block)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("withRecordVoiceAction", "dev.inmo.tgbotapi.extensions.api.send.withRecordVoiceAction")
)
suspend fun <T> TelegramBot.withRecordAudioAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordAudioAction, block) suspend fun <T> TelegramBot.withRecordAudioAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordAudioAction, block)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("withUploadVoiceAction", "dev.inmo.tgbotapi.extensions.api.send.withUploadVoiceAction")
)
suspend fun <T> TelegramBot.withUploadAudioAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadAudioAction, block) suspend fun <T> TelegramBot.withUploadAudioAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadAudioAction, block)
suspend fun <T> TelegramBot.withRecordVoiceAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordVoiceAction, block)
suspend fun <T> TelegramBot.withUploadVoiceAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadVoiceAction, block)
suspend fun <T> TelegramBot.withUploadDocumentAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadDocumentAction, block) suspend fun <T> TelegramBot.withUploadDocumentAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, UploadDocumentAction, block)
suspend fun <T> TelegramBot.withFindLocationAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, FindLocationAction, block) suspend fun <T> TelegramBot.withFindLocationAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, FindLocationAction, block)
suspend fun <T> TelegramBot.withRecordVideoNoteAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordVideoNoteAction, block) suspend fun <T> TelegramBot.withRecordVideoNoteAction(chatId: ChatId, block: TelegramBotActionCallback<T>) = withAction(chatId, RecordVideoNoteAction, block)
@ -68,8 +78,18 @@ suspend fun <T> TelegramBot.withTypingAction(chat: Chat, block: TelegramBotActio
suspend fun <T> TelegramBot.withUploadPhotoAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadPhotoAction, block) suspend fun <T> TelegramBot.withUploadPhotoAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadPhotoAction, block)
suspend fun <T> TelegramBot.withRecordVideoAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordVideoAction, block) suspend fun <T> TelegramBot.withRecordVideoAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordVideoAction, block)
suspend fun <T> TelegramBot.withUploadVideoAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadVideoAction, block) suspend fun <T> TelegramBot.withUploadVideoAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadVideoAction, block)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("withRecordVoiceAction", "dev.inmo.tgbotapi.extensions.api.send.withRecordVoiceAction")
)
suspend fun <T> TelegramBot.withRecordAudioAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordAudioAction, block) suspend fun <T> TelegramBot.withRecordAudioAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordAudioAction, block)
@Deprecated(
"Deprecated according to https://core.telegram.org/bots/api-changelog#april-26-2021",
ReplaceWith("withUploadVoiceAction", "dev.inmo.tgbotapi.extensions.api.send.withUploadVoiceAction")
)
suspend fun <T> TelegramBot.withUploadAudioAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadAudioAction, block) suspend fun <T> TelegramBot.withUploadAudioAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadAudioAction, block)
suspend fun <T> TelegramBot.withRecordVoiceAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordVoiceAction, block)
suspend fun <T> TelegramBot.withUploadVoiceAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadVoiceAction, block)
suspend fun <T> TelegramBot.withUploadDocumentAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadDocumentAction, block) suspend fun <T> TelegramBot.withUploadDocumentAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, UploadDocumentAction, block)
suspend fun <T> TelegramBot.withFindLocationAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, FindLocationAction, block) suspend fun <T> TelegramBot.withFindLocationAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, FindLocationAction, block)
suspend fun <T> TelegramBot.withRecordVideoNoteAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordVideoNoteAction, block) suspend fun <T> TelegramBot.withRecordVideoNoteAction(chat: Chat, block: TelegramBotActionCallback<T>) = withAction(chat, RecordVideoNoteAction, block)

View File

@ -16,7 +16,7 @@ import dev.inmo.tgbotapi.types.message.abstracts.Message
suspend fun TelegramBot.sendPhoto( suspend fun TelegramBot.sendPhoto(
chatId: ChatIdentifier, chatId: ChatIdentifier,
fileId: InputFile, fileId: InputFile,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
@ -26,7 +26,7 @@ suspend fun TelegramBot.sendPhoto(
SendPhoto( SendPhoto(
chatId, chatId,
fileId, fileId,
caption, text,
parseMode, parseMode,
disableNotification, disableNotification,
replyToMessageId, replyToMessageId,
@ -38,65 +38,65 @@ suspend fun TelegramBot.sendPhoto(
suspend fun TelegramBot.sendPhoto( suspend fun TelegramBot.sendPhoto(
chat: Chat, chat: Chat,
fileId: InputFile, fileId: InputFile,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, fileId, caption, parseMode, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendPhoto(chat.id, fileId, text, parseMode, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
suspend fun TelegramBot.sendPhoto( suspend fun TelegramBot.sendPhoto(
chatId: ChatIdentifier, chatId: ChatIdentifier,
photo: Photo, photo: Photo,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photo.biggest() ?.fileId ?: error("Photo content must not be empty"), caption, parseMode, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendPhoto(chatId, photo.biggest() ?.fileId ?: error("Photo content must not be empty"), text, parseMode, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
suspend fun TelegramBot.sendPhoto( suspend fun TelegramBot.sendPhoto(
chat: Chat, chat: Chat,
photo: Photo, photo: Photo,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, photo, caption, parseMode, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendPhoto(chat.id, photo, text, parseMode, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithPhoto( suspend inline fun TelegramBot.replyWithPhoto(
to: Message, to: Message,
fileId: InputFile, fileId: InputFile,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, fileId, caption, parseMode, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup) ) = sendPhoto(to.chat, fileId, text, parseMode, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithPhoto( suspend inline fun TelegramBot.replyWithPhoto(
to: Message, to: Message,
photo: Photo, photo: Photo,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, photo, caption, parseMode, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup) ) = sendPhoto(to.chat, photo, text, parseMode, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply( suspend inline fun TelegramBot.reply(
to: Message, to: Message,
photo: Photo, photo: Photo,
caption: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = replyWithPhoto(to, photo, caption, parseMode, disableNotification, allowSendingWithoutReply, replyMarkup) ) = replyWithPhoto(to, photo, text, parseMode, disableNotification, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.sendPhoto( suspend inline fun TelegramBot.sendPhoto(

View File

@ -14,9 +14,11 @@ suspend fun TelegramBot.sendInvoice(
description: String, description: String,
payload: String, payload: String,
providerToken: String, providerToken: String,
startParameter: StartParameter,
currency: Currency, currency: Currency,
prices: List<LabeledPrice>, prices: List<LabeledPrice>,
maxTipAmount: Int? = null,
suggestedTipAmounts: List<Int>? = null,
startParameter: StartParameter? = null,
providerData: String? = null, providerData: String? = null,
requireName: Boolean = false, requireName: Boolean = false,
requirePhoneNumber: Boolean = false, requirePhoneNumber: Boolean = false,
@ -30,7 +32,7 @@ suspend fun TelegramBot.sendInvoice(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null replyMarkup: InlineKeyboardMarkup? = null
) = execute( ) = execute(
SendInvoice(chatId, title, description, payload, providerToken, startParameter, currency, prices, providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup) SendInvoice(chatId, title, description, payload, providerToken, currency, prices, maxTipAmount, suggestedTipAmounts ?.sorted(), startParameter, providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) )
suspend fun TelegramBot.sendInvoice( suspend fun TelegramBot.sendInvoice(
@ -39,9 +41,11 @@ suspend fun TelegramBot.sendInvoice(
description: String, description: String,
payload: String, payload: String,
providerToken: String, providerToken: String,
startParameter: StartParameter,
currency: Currency, currency: Currency,
prices: List<LabeledPrice>, prices: List<LabeledPrice>,
maxTipAmount: Int? = null,
suggestedTipAmounts: List<Int>? = null,
startParameter: StartParameter? = null,
providerData: String? = null, providerData: String? = null,
requireName: Boolean = false, requireName: Boolean = false,
requirePhoneNumber: Boolean = false, requirePhoneNumber: Boolean = false,
@ -54,7 +58,7 @@ suspend fun TelegramBot.sendInvoice(
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null replyMarkup: InlineKeyboardMarkup? = null
) = sendInvoice(user.id, title, description, payload, providerToken, startParameter, currency, prices, providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendInvoice(user.id, title, description, payload, providerToken, currency, prices, maxTipAmount, suggestedTipAmounts, startParameter, providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithInvoice( suspend inline fun TelegramBot.replyWithInvoice(
to: Message, to: Message,
@ -62,9 +66,11 @@ suspend inline fun TelegramBot.replyWithInvoice(
description: String, description: String,
payload: String, payload: String,
providerToken: String, providerToken: String,
startParameter: StartParameter,
currency: Currency, currency: Currency,
prices: List<LabeledPrice>, prices: List<LabeledPrice>,
maxTipAmount: Int? = null,
suggestedTipAmounts: List<Int>? = null,
startParameter: StartParameter? = null,
providerData: String? = null, providerData: String? = null,
requireName: Boolean = false, requireName: Boolean = false,
requirePhoneNumber: Boolean = false, requirePhoneNumber: Boolean = false,
@ -76,4 +82,4 @@ suspend inline fun TelegramBot.replyWithInvoice(
disableNotification: Boolean = false, disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null replyMarkup: InlineKeyboardMarkup? = null
) = sendInvoice(to.chat.id, title, description, payload, providerToken, startParameter, currency, prices, providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup) ) = sendInvoice(to.chat.id, title, description, payload, providerToken, currency, prices, maxTipAmount, suggestedTipAmounts, startParameter, providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup)

View File

@ -2,7 +2,8 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder
import dev.inmo.micro_utils.coroutines.DeferredAction import dev.inmo.micro_utils.coroutines.DeferredAction
import dev.inmo.micro_utils.coroutines.invokeFirstOf import dev.inmo.micro_utils.coroutines.invokeFirstOf
import kotlinx.coroutines.* import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
suspend fun <T> BehaviourContext.parallel( suspend fun <T> BehaviourContext.parallel(
action: BehaviourContextReceiver<T> action: BehaviourContextReceiver<T>

View File

@ -1,10 +1,7 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.CallbackQuery.CallbackQuery
import dev.inmo.tgbotapi.types.CallbackQuery.DataCallbackQuery
import dev.inmo.tgbotapi.types.ChatMemberUpdated import dev.inmo.tgbotapi.types.ChatMemberUpdated
import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate
import dev.inmo.tgbotapi.types.update.MyChatMemberUpdatedUpdate import dev.inmo.tgbotapi.types.update.MyChatMemberUpdatedUpdate

View File

@ -3,7 +3,6 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.utils.asChatMemberUpdatedUpdate
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.ChatMemberUpdated import dev.inmo.tgbotapi.types.ChatMemberUpdated
import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate

View File

@ -1,8 +1,8 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.tgbotapi.CommonAbstracts.textSources import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver
import dev.inmo.tgbotapi.extensions.utils.* import dev.inmo.tgbotapi.extensions.utils.asBotCommandTextSource
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.message.content.TextContent
import kotlinx.coroutines.Job import kotlinx.coroutines.Job

View File

@ -1,8 +1,8 @@
@file:Suppress("NOTHING_TO_INLINE", "unused", "UNCHECKED_CAST") @file:Suppress("NOTHING_TO_INLINE", "unused", "UNCHECKED_CAST")
package dev.inmo.tgbotapi.extensions.utils package dev.inmo.tgbotapi.extensions.utils
import dev.inmo.tgbotapi.CommonAbstracts.MultilevelTextSource import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.CommonAbstracts.TextSource import dev.inmo.tgbotapi.requests.send.payments.SendInvoice
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.CallbackQuery.* import dev.inmo.tgbotapi.types.CallbackQuery.*
import dev.inmo.tgbotapi.types.ChatMember.* import dev.inmo.tgbotapi.types.ChatMember.*
@ -525,6 +525,10 @@ inline fun BotAction.asRecordAudioAction(): RecordAudioAction? = this as? Record
@PreviewFeature @PreviewFeature
inline fun BotAction.requireRecordAudioAction(): RecordAudioAction = this as RecordAudioAction inline fun BotAction.requireRecordAudioAction(): RecordAudioAction = this as RecordAudioAction
@PreviewFeature @PreviewFeature
inline fun BotAction.asRecordVoiceAction(): RecordVoiceAction? = this as? RecordVoiceAction
@PreviewFeature
inline fun BotAction.requireRecordVoiceAction(): RecordVoiceAction = this as RecordVoiceAction
@PreviewFeature
inline fun BotAction.asRecordVideoAction(): RecordVideoAction? = this as? RecordVideoAction inline fun BotAction.asRecordVideoAction(): RecordVideoAction? = this as? RecordVideoAction
@PreviewFeature @PreviewFeature
inline fun BotAction.requireRecordVideoAction(): RecordVideoAction = this as RecordVideoAction inline fun BotAction.requireRecordVideoAction(): RecordVideoAction = this as RecordVideoAction
@ -541,6 +545,10 @@ inline fun BotAction.asUploadAudioAction(): UploadAudioAction? = this as? Upload
@PreviewFeature @PreviewFeature
inline fun BotAction.requireUploadAudioAction(): UploadAudioAction = this as UploadAudioAction inline fun BotAction.requireUploadAudioAction(): UploadAudioAction = this as UploadAudioAction
@PreviewFeature @PreviewFeature
inline fun BotAction.asUploadVoiceAction(): UploadVoiceAction? = this as? UploadVoiceAction
@PreviewFeature
inline fun BotAction.requireUploadVoiceAction(): UploadVoiceAction = this as UploadVoiceAction
@PreviewFeature
inline fun BotAction.asUploadDocumentAction(): UploadDocumentAction? = this as? UploadDocumentAction inline fun BotAction.asUploadDocumentAction(): UploadDocumentAction? = this as? UploadDocumentAction
@PreviewFeature @PreviewFeature
inline fun BotAction.requireUploadDocumentAction(): UploadDocumentAction = this as UploadDocumentAction inline fun BotAction.requireUploadDocumentAction(): UploadDocumentAction = this as UploadDocumentAction
@ -581,6 +589,10 @@ inline fun InputMessageContent.asInputVenueMessageContent(): InputVenueMessageCo
@PreviewFeature @PreviewFeature
inline fun InputMessageContent.requireInputVenueMessageContent(): InputVenueMessageContent = this as InputVenueMessageContent inline fun InputMessageContent.requireInputVenueMessageContent(): InputVenueMessageContent = this as InputVenueMessageContent
@PreviewFeature @PreviewFeature
inline fun InputMessageContent.asInputInvoiceMessageContent(): InputInvoiceMessageContent? = this as? InputInvoiceMessageContent
@PreviewFeature
inline fun InputMessageContent.requireInputInvoiceMessageContent(): InputInvoiceMessageContent = this as InputInvoiceMessageContent
@PreviewFeature
inline fun InlineQueryResult.asInlineQueryResultArticle(): InlineQueryResultArticle? = this as? InlineQueryResultArticle inline fun InlineQueryResult.asInlineQueryResultArticle(): InlineQueryResultArticle? = this as? InlineQueryResultArticle
@PreviewFeature @PreviewFeature
inline fun InlineQueryResult.requireInlineQueryResultArticle(): InlineQueryResultArticle = this as InlineQueryResultArticle inline fun InlineQueryResult.requireInlineQueryResultArticle(): InlineQueryResultArticle = this as InlineQueryResultArticle
@ -1296,3 +1308,11 @@ inline fun ChatEvent.requireVoiceChatParticipantsInvited(): VoiceChatParticipant
inline fun ChatEvent.asVoiceChatStarted(): VoiceChatStarted? = this as? VoiceChatStarted inline fun ChatEvent.asVoiceChatStarted(): VoiceChatStarted? = this as? VoiceChatStarted
@PreviewFeature @PreviewFeature
inline fun ChatEvent.requireVoiceChatStarted(): VoiceChatStarted = this as VoiceChatStarted inline fun ChatEvent.requireVoiceChatStarted(): VoiceChatStarted = this as VoiceChatStarted
@PreviewFeature
inline fun CommonSendInvoiceData.asSendInvoice(): SendInvoice? = this as? SendInvoice
@PreviewFeature
inline fun CommonSendInvoiceData.requireVoiceChatParticipantsInvited(): SendInvoice = this as SendInvoice
@PreviewFeature
inline fun CommonSendInvoiceData.asInputInvoiceMessageContent(): InputInvoiceMessageContent? = this as? InputInvoiceMessageContent
@PreviewFeature
inline fun CommonSendInvoiceData.requireInputInvoiceMessageContent(): InputInvoiceMessageContent = this as InputInvoiceMessageContent

View File

@ -7,7 +7,6 @@ import dev.inmo.tgbotapi.types.message.content.media.*
import dev.inmo.tgbotapi.types.message.payments.InvoiceContent import dev.inmo.tgbotapi.types.message.payments.InvoiceContent
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.mapNotNull
import kotlin.reflect.KClass
private inline fun <reified T : MessageContent> Flow<ContentMessage<*>>.withContentType() = mapNotNull { private inline fun <reified T : MessageContent> Flow<ContentMessage<*>>.withContentType() = mapNotNull {
it.withContent<T>() it.withContent<T>()

View File

@ -4,7 +4,6 @@ import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
val defaultArgsSeparator = Regex(" ") val defaultArgsSeparator = Regex(" ")
@ -19,10 +18,13 @@ fun List<TextSource>.parseCommandsWithParams(
var currentArgs = "" var currentArgs = ""
fun includeCurrent() = currentBotCommandSource ?.let { fun includeCurrent() = currentBotCommandSource ?.let {
currentArgs = currentArgs.trim() currentArgs = currentArgs.trim()
if (currentArgs.isNotEmpty()) { result[it.command] = if (currentArgs.isNotEmpty()) {
result[it.command] = currentArgs.split(argsSeparator).toTypedArray() currentArgs.split(argsSeparator).toTypedArray()
currentArgs = "" } else {
emptyArray()
} }
currentArgs = ""
currentBotCommandSource = null
} }
for (textSource in this) { for (textSource in this) {
if (textSource is BotCommandTextSource) { if (textSource is BotCommandTextSource) {
@ -39,23 +41,9 @@ fun List<TextSource>.parseCommandsWithParams(
/** /**
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command * Parse commands and their args. Logic will find command, get all subsequent data as args until new command
*/ */
fun TextedInput.parseCommandsWithParams( fun TextedWithTextSources.parseCommandsWithParams(
argsSeparator: Regex = defaultArgsSeparator argsSeparator: Regex = defaultArgsSeparator
) = textSources.parseCommandsWithParams(argsSeparator) ) = textSources ?.parseCommandsWithParams(argsSeparator) ?: emptyMap()
/**
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
*/
fun TextedOutput.parseCommandsWithParams(
argsSeparator: Regex = defaultArgsSeparator
) = entities ?.parseCommandsWithParams(argsSeparator) ?: emptyMap()
/**
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
*/
fun CaptionedInput.parseCommandsWithParams(
argsSeparator: Regex = defaultArgsSeparator
) = textSources.parseCommandsWithParams(argsSeparator)
/** /**
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command * Parse commands and their args. Logic will find command, get all subsequent data as args until new command

View File

@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.extensions.utils.shortcuts package dev.inmo.tgbotapi.extensions.utils.shortcuts
import dev.inmo.tgbotapi.CommonAbstracts.TextSource import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.extensions.utils.onlyTextContentMessages import dev.inmo.tgbotapi.extensions.utils.onlyTextContentMessages
import dev.inmo.tgbotapi.extensions.utils.updates.asContentMessagesFlow import dev.inmo.tgbotapi.extensions.utils.updates.asContentMessagesFlow
import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource

View File

@ -1,9 +1,8 @@
package dev.inmo.tgbotapi.types.files package dev.inmo.tgbotapi.types.files
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import java.io.*
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.net.URL import java.net.URL
fun PathedFile.asStream( fun PathedFile.asStream(