1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-17 04:20:13 +00:00

Compare commits

..

47 Commits

Author SHA1 Message Date
0c11be7fe4 rewrite work with Bot class 2020-01-23 22:32:45 +06:00
7a880ba2bd UnknownPollType now can be created only inside of library 2020-01-23 22:15:08 +06:00
1a258ae912 RequestPollKeyboardButton#requestPoll is required parameter for now 2020-01-23 22:09:06 +06:00
9dc3e1ecc6 fixes in KeyboardButtonPollType serialization 2020-01-23 21:52:28 +06:00
b9e674821b fix in createRequest for Poll 2020-01-23 20:45:02 +06:00
f4a731940e QuizPoll#correctOptionId now is nullable 2020-01-23 20:40:56 +06:00
43ef7656d0 startGettingUpdates now have parameter for pollAnswer 2020-01-23 20:13:32 +06:00
b9ab7f2955 AnonymousPollOption renamed to SimplePollOption 2020-01-23 20:11:24 +06:00
00886dcfb7 now user have correct serializer 2020-01-23 19:31:09 +06:00
46573512a2 fix in javaLocale extension 2020-01-23 19:14:33 +06:00
a8ae0a296a separated User object and additional fields for Bot representation 2020-01-23 19:08:02 +06:00
8687a2ba6b "KeyboardButton" now is sealed class 2020-01-23 18:06:22 +06:00
dbd9c72249 UpdatesFilter now support PollAnswerUpdate 2020-01-23 17:32:04 +06:00
7aef76f432 PollAnswerUpdate 2020-01-23 17:29:09 +06:00
aece0784ab fixes in PollContent#createResend, added Poll#createRequest 2020-01-23 17:25:57 +06:00
4e1dbb8741 PollAnswer 2020-01-23 17:17:24 +06:00
41db785696 "language" field im RawMessageEntity 2020-01-23 17:07:28 +06:00
4e39f77b53 SendRegularPoll, SendQuizPoll 2020-01-23 17:01:13 +06:00
258ab44bac added votes count field to poll 2020-01-23 16:40:57 +06:00
423efafa04 extend polls 2020-01-23 16:36:25 +06:00
229334e781 start 0.23.0 2020-01-23 16:00:46 +06:00
c4f22c2c43 Merge pull request #62 from InsanusMokrassar/0.22.2
0.22.2
2020-01-23 04:23:23 +06:00
2980b345a9 optimize imports 2020-01-23 04:23:06 +06:00
ca24416934 UpdatesFilter#unknownUpdateTypeCallback 2020-01-23 04:21:45 +06:00
c006b47429 fix in cashTag internal fun 2020-01-23 04:08:56 +06:00
8487ee1f31 fixes in calling of "asUpdate" 2020-01-23 04:01:24 +06:00
f4fe680cac UnknownCallbackQueryType 2020-01-23 03:59:59 +06:00
cf814fcecb update gradle.properties 2020-01-23 03:51:08 +06:00
a967b06d2e remove redundant line from changelog 2020-01-23 03:48:33 +06:00
83e5d40443 UnknownUpdate -> UnknownUpdateType, unknown types for messages and chats 2020-01-23 03:47:43 +06:00
a8ca45a4bd replace UnknownUpdate 2020-01-23 03:35:56 +06:00
961fa65415 UnknownUpdate 2020-01-23 03:31:56 +06:00
4182d66f6e cashtag entity type was added 2020-01-23 03:05:28 +06:00
971589fe99 start 0.22.2 2020-01-23 03:03:38 +06:00
257574324a Update README.md 2020-01-21 16:03:02 +06:00
cf3e372ca3 Added a cut for README 2020-01-21 16:01:53 +06:00
502a53fd62 fixes in new "asInputMedia" functions 2020-01-21 14:30:33 +06:00
353891eb37 Merge pull request #60 from InsanusMokrassar/0.22.1
0.22.1
2020-01-20 22:39:23 +06:00
5f593439a3 remove file link maker 2020-01-20 22:38:45 +06:00
f99873dd70 hotfix 2020-01-20 22:10:46 +06:00
d330cd2bfc hotfix 2020-01-20 20:14:52 +06:00
92224b95df PreviewFeature, message links 2020-01-20 16:35:36 +06:00
63e0f5c054 0.22.1 2020-01-20 14:42:38 +06:00
dd76e704a8 Update README.md 2020-01-17 08:29:22 +06:00
4845a61539 Update README.md 2020-01-17 08:24:38 +06:00
9dfb16f534 update publish scripts 2020-01-15 21:41:52 +06:00
50ae9ef955 Merge pull request #59 from InsanusMokrassar/0.22.0
0.22.0
2020-01-15 13:35:08 +06:00
65 changed files with 1007 additions and 244 deletions

View File

@@ -1,5 +1,40 @@
# TelegramBotAPI changelog
## 0.23.0 TelegramBotAPI 4.6
* `Poll` now is sealed class
* `RegularPoll` type was added to represent polls with type `regular`
* `QuizPoll` type was added to represent polls with type `quiz`
* `UnknownPollType` type was added to represent polls which are unknown in current version
* `AnonymousPollOption` was renamed to `SimplePollOption`
* `SendPoll` was rewritten as sealed class
* `SendRegularPoll` was created and represent `sendPoll` method with type `regular`
* `SendQuizPoll` was created and represent `sendPoll` method with type `quiz`
* `Poll#createRequest` extension was added
* `PollAnswerUpdate` type of update was added
* `PollAnswer` type was added
* `UpdatesFilter` now support work with `PollAnswerUpdate`
* `language` field in PreTextSource now correctly passed from telegram MessageEntities
* `KeyboardButton` now is sealed class
* Fixed problem of incorrect representation of this class (any type of request can be created separately)
* Added new types of `KeyboardButton`:
* `UnknownKeyboardButton`
* `SimpleKeyboardButton`
* `RequestContactKeyboardButton`
* `RequestLocationKeyboardButton`
* `RequestPollKeyboardButton`
* Added new type `KeyboardButtonPollType`:
* `UnknownKeyboardButtonPollType`
* `RegularKeyboardButtonPollType`
* `QuizKeyboardButtonPollType`
* `User` now is sealed class
* `CommonUser` was added as representation of default `User`
* `Bot` was added as representation of bot user (it is sealed class)
* `ExtendedBot` with additional info
* `CommonBot` with simple info
* `GetMe` now return `ExtendedBot` object
* Now extension `javaLocale` is extension for `CommonUser`
## 0.22.0
* **`KtorCallFactory` must return `HttpStatement` instead of `HttpClientCall`**
@@ -68,6 +103,26 @@ mistake - don't hesitate to say this.**
* Version updates:
* Ktor `1.2.6` -> `1.3.0`
### 0.22.1 MediaContent#asInputMedia
* All `MediaContent` instances now can create their `InputMedia` analog
* New annotation `PreviewFeature` was added to mark new thing as preview for the time
while they can work incorrectly
* Added links utils:
* `makeLinkToMessage` have two signatures - for direct creating using username and for abstract creating using
chat id
### 0.22.2 CashTag and independent updates handling
* `cashtag` entity type was added
* Several `Unknown*` realizations was added:
* `UnknownUpdateType`
* `UnknownMessageType`
* `UnknownChatType`
* `UnknownCallbackQueryType`
* `UpdatesFilter` now have one additional income callback: `unknownUpdateTypeCallback`
* `createSimpleUpdateFilter` can receive one more callback: `unknownCallback` (for `unknownUpdateTypeCallback`)
## 0.21.0 TelegramBotAPI 4.5
* _**All `MessageEntity`'es now are replaced with `TextPart`**_

View File

@@ -10,7 +10,7 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
## Compatibility
This version compatible with [31th of December 2019 update of TelegramBotAPI (version 4.5)](https://core.telegram.org/bots/api#december-31-2019).
This version compatible with [23th of January 2020 update of TelegramBotAPI (version 4.6)](https://core.telegram.org/bots/api#january-23-2020).
There is Telegram Passport API exception of implemented functionality, which was presented in
[August 2018 update of TelegramBotAPI](https://core.telegram.org/bots/api#august-27-2018) update. It will be implemented
as soon as possible. All APIs that are not included are presented
@@ -25,7 +25,7 @@ like inserting of additional libraries (like `kotlin stdlib`). In the examples w
[![Download](https://api.bintray.com/packages/insanusmokrassar/StandardRepository/TelegramBotAPI/images/download.svg) ](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI/_latestVersion)
Currently, last versions of library are not included into the Maven repository (for the reason difficult in publishing
Currently, last versions of library can be available from the Maven repository with errors (for the reason difficult in publishing
of signed artifacts in Bintray). You can:
* Use earlier version (available version you can find
@@ -96,10 +96,9 @@ val requestsExecutor: RequestsExecutor = ...
requestsExecutor.execute(GetMe())
```
The result type of [GetMe](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/GetMe.kt) request is
[User](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/User.kt). In fact, in this result must contain
`isBot` equal to `true` always.
The result type of [GetMe](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/GetMe.kt)
request is
[ExtendedBot](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/User.kt).
### RequestsExecutor
@@ -155,7 +154,7 @@ Currently webhook method contains `UpdatesFilter` as necessary argument for gett
separate getting updates for media groups - they are accumulating with debounce in one second
(for being sure that all objects of media group was received).
Updates polling also support `UpdatesFilter` but you must not use it and can get updates directly
Updates polling also support `UpdatesFilter` but it is not required to use it and you can get updates directly
in `UpdateReceiver`, which you will provide to `startGettingOfUpdates` method
### Webhook set up

View File

@@ -17,7 +17,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
}
project.version = "0.22.0"
project.version = "0.23.0"
project.group = "com.github.insanusmokrassar"
apply from: "publish.gradle"

View File

@@ -7,6 +7,3 @@ uuid_version=0.0.7
ktor_version=1.3.0
gradle_bintray_plugin_version=1.8.4
project_public_name=Telegram Bot API
project_public_description=Library for Object-Oriented and type-safe work with Telegram Bot API

View File

@@ -8,16 +8,19 @@ bintray {
filesSpec {
from "${buildDir}/publications/"
eachFile {
String directorySubname = it.getFile().parentFile.name
if (it.getName() == "module.json") {
File file = it.getFile()
String directorySubname = file.parentFile.name
if (directorySubname == "kotlinMultiplatform") {
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
} else {
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
}
} else {
it.exclude()
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
} else {
it.exclude()
}
}
}
into "${project.group}".replace(".", "/")

View File

@@ -2,7 +2,6 @@ package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import io.ktor.client.HttpClient
import io.ktor.client.call.HttpClientCall
import io.ktor.client.statement.HttpStatement
interface KtorCallFactory {

View File

@@ -3,7 +3,6 @@ package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorCallFactory
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import io.ktor.client.HttpClient
import io.ktor.client.call.HttpClientCall
import io.ktor.client.request.*
import io.ktor.client.statement.HttpStatement
import io.ktor.http.ContentType

View File

@@ -3,7 +3,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.requests
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.types.MessageAction
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.SimpleRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.PossiblyForwardedMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import kotlinx.serialization.*
private val AbleToBeForwardedMessageDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<PossiblyForwardedMessage>()

View File

@@ -1,14 +1,14 @@
package com.github.insanusmokrassar.TelegramBotAPI.requests
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.SimpleRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.User
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import kotlinx.serialization.*
@Serializable
class GetMe : SimpleRequest<User> {
class GetMe : SimpleRequest<ExtendedBot> {
override fun method(): String = "getMe"
override val resultDeserializer: DeserializationStrategy<User>
get() = User.serializer()
override val resultDeserializer: DeserializationStrategy<ExtendedBot>
get() = ExtendedBot.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -3,7 +3,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.requests.chat.get
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.types.ChatRequest
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.SimpleRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatMember.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatMember.abstracts.AdministratorChatMember
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatMember.abstracts.AdministratorChatMemberSerializerWithoutDeserialization
import com.github.insanusmokrassar.TelegramBotAPI.types.chatIdField
import kotlinx.serialization.*
import kotlinx.serialization.internal.ArrayListSerializer

View File

@@ -3,11 +3,9 @@ package com.github.insanusmokrassar.TelegramBotAPI.requests.edit.LiveLocation
import com.github.insanusmokrassar.TelegramBotAPI.requests.edit.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.LocationContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import kotlinx.serialization.*
private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<ContentMessage<LocationContent>>()

View File

@@ -4,8 +4,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.edit.abstracts.EditCh
import com.github.insanusmokrassar.TelegramBotAPI.requests.edit.abstracts.EditReplyMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.LocationContent
import kotlinx.serialization.*

View File

@@ -4,9 +4,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.edit.abstracts.EditCh
import com.github.insanusmokrassar.TelegramBotAPI.requests.edit.abstracts.EditReplyMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import kotlinx.serialization.*

View File

@@ -6,9 +6,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import kotlinx.serialization.*

View File

@@ -5,7 +5,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.edit.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMedia
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import kotlinx.serialization.*

View File

@@ -6,8 +6,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import kotlinx.serialization.*

View File

@@ -4,8 +4,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.Replyi
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.SendMessageRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.ContactContent
import kotlinx.serialization.*

View File

@@ -3,8 +3,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.requests.send
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.LocationContent
import kotlinx.serialization.*

View File

@@ -6,7 +6,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import kotlinx.serialization.*

View File

@@ -1,51 +0,0 @@
package com.github.insanusmokrassar.TelegramBotAPI.requests.send
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.SendMessageRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.PollContent
import kotlinx.serialization.*
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PollContent>>
= TelegramBotAPIMessageDeserializationStrategyClass()
@Serializable
data class SendPoll(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(questionField)
val question: String,
@SerialName(optionsField)
val options: List<String>,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<PollContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<PollContent>> {
init {
if (question.length !in pollQuestionTextLength) {
throw IllegalArgumentException("The length of questions for polls must be in $pollQuestionTextLength range, but was ${question.length}")
}
options.forEach {
if (it.length !in pollOptionTextLength) {
throw IllegalArgumentException("The length of question option text for polls must be in $pollOptionTextLength range, but was ${it.length}")
}
}
if (options.size !in pollOptionsLimit) {
throw IllegalArgumentException("The amount of question options for polls must be in $pollOptionsLimit range, but was ${options.size}")
}
}
override fun method(): String = "sendPoll"
override val resultDeserializer: DeserializationStrategy<ContentMessage<PollContent>>
get() = commonResultDeserializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -3,7 +3,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.requests.send
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.VenueContent
import kotlinx.serialization.*

View File

@@ -4,8 +4,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.types.ReplyMar
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.SendMessageRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategy
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.GameContent
import kotlinx.serialization.*

View File

@@ -0,0 +1,185 @@
package com.github.insanusmokrassar.TelegramBotAPI.requests.send.polls
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.SendMessageRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.PollContent
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.*
import kotlinx.serialization.*
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PollContent>> = TelegramBotAPIMessageDeserializationStrategyClass()
private fun checkPollInfo(
question: String,
options: List<String>
) {
if (question.length !in pollQuestionTextLength) {
throw IllegalArgumentException("The length of questions for polls must be in $pollQuestionTextLength range, but was ${question.length}")
}
options.forEach {
if (it.length !in pollOptionTextLength) {
throw IllegalArgumentException("The length of question option text for polls must be in $pollOptionTextLength range, but was ${it.length}")
}
}
if (options.size !in pollOptionsLimit) {
throw IllegalArgumentException("The amount of question options for polls must be in $pollOptionsLimit range, but was ${options.size}")
}
}
fun SendPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
replyMarkup: KeyboardMarkup? = null
) = SendRegularPoll(
chatId,
question,
options,
isAnonymous,
isClosed,
disableNotification = disableNotification,
replyToMessageId = replyToMessageId,
replyMarkup = replyMarkup
)
/**
* @return [SendPoll] in case when all is right. It can return [SendRegularPoll] for [QuizPoll] in case if
* [QuizPoll.correctOptionId] equal to null
*/
fun Poll.createRequest(
chatId: ChatIdentifier,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
replyMarkup: KeyboardMarkup? = null
) = when (this) {
is RegularPoll -> SendRegularPoll(
chatId,
question,
options.map { it.text },
isAnonymous,
isClosed,
allowMultipleAnswers,
disableNotification,
replyToMessageId,
replyMarkup
)
is QuizPoll -> correctOptionId ?.let { correctOptionId ->
SendQuizPoll(
chatId,
question,
options.map { it.text },
correctOptionId,
isAnonymous,
isClosed,
disableNotification,
replyToMessageId,
replyMarkup
)
} ?: SendRegularPoll(
chatId,
question,
options.map { it.text },
isAnonymous,
isClosed,
false,
disableNotification,
replyToMessageId,
replyMarkup
)
is UnknownPollType -> SendRegularPoll(
chatId,
question,
options.map { it.text },
isAnonymous,
isClosed,
false,
disableNotification,
replyToMessageId,
replyMarkup
)
}
sealed class SendPoll : SendMessageRequest<ContentMessage<PollContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<PollContent>> {
abstract val question: String
abstract val options: List<String>
abstract val isAnonymous: Boolean
abstract val isClosed: Boolean
abstract val type: String
override fun method(): String = "sendPoll"
override val resultDeserializer: DeserializationStrategy<ContentMessage<PollContent>>
get() = commonResultDeserializer
}
@Serializable
data class SendRegularPoll(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(questionField)
override val question: String,
@SerialName(optionsField)
override val options: List<String>,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = true,
@SerialName(isClosedField)
override val isClosed: Boolean = false,
@SerialName(allowsMultipleAnswersField)
val allowMultipleAnswers: Boolean = false,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendPoll() {
override val type: String = regularPollType
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
init {
checkPollInfo(question, options)
}
}
@Serializable
data class SendQuizPoll(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(questionField)
override val question: String,
@SerialName(optionsField)
override val options: List<String>,
@SerialName(correctOptionIdField)
val correctOptionId: Int,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = true,
@SerialName(isClosedField)
override val isClosed: Boolean = false,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendPoll() {
override val type: String = quizPollType
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
init {
checkPollInfo(question, options)
val correctOptionIdRange = 0 .. options.size
if (correctOptionId !in correctOptionIdRange) {
throw IllegalArgumentException("Correct option id must be in range of $correctOptionIdRange, but actual " +
"value is $correctOptionId")
}
}
}

View File

@@ -7,4 +7,11 @@ interface CallbackQuery {
val id: CallbackQueryIdentifier
val user: User
val chatInstance: String
}
}
data class UnknownCallbackQueryType(
override val id: CallbackQueryIdentifier,
override val user: User,
override val chatInstance: String,
val raw: String
) : CallbackQuery

View File

@@ -22,13 +22,21 @@ internal data class RawCallbackQuery(
@SerialName("game_short_name")
val gameShortName: String? = null
) {
val asCallbackQuery: CallbackQuery by lazy {
when {
private var inited: CallbackQuery? = null
fun asCallbackQuery(raw: String): CallbackQuery {
return inited ?: when {
message != null && data != null -> MessageDataCallbackQuery(id, from, chatInstance, message, data)
message != null && gameShortName != null -> MessageGameShortNameCallbackQuery(id, from, chatInstance, message, gameShortName)
inlineMessageId != null && data != null -> InlineMessageIdDataCallbackQuery(id, from, chatInstance, inlineMessageId, data)
inlineMessageId != null && gameShortName != null -> InlineMessageIdGameShortNameCallbackQuery(id, from, chatInstance, inlineMessageId, gameShortName)
else -> throw IllegalStateException("Strange answer from server, can't create callback query")
else -> UnknownCallbackQueryType(
id,
from,
chatInstance,
raw
)
}.also {
inited = it
}
}
}

View File

@@ -57,6 +57,9 @@ const val isBotField = "is_bot"
const val firstNameField = "first_name"
const val lastNameField = "last_name"
const val languageCodeField = "language_code"
const val canJoinGroupsField = "can_join_groups"
const val canReadAllGroupMessagesField = "can_read_all_group_messages"
const val supportInlineQueriesField = "supports_inline_queries"
const val textEntitiesField = "text_entities"
const val stickerSetNameField = "set_name"
const val stickerSetNameFullField = "sticker_set_name"
@@ -90,6 +93,10 @@ const val lastErrorDateField = "last_error_date"
const val lastErrorMessageField = "last_error_message"
const val votesCountField = "voter_count"
const val isClosedField = "is_closed"
const val totalVoterCountField = "total_voter_count"
const val correctOptionIdField = "correct_option_id"
const val allowsMultipleAnswersField = "allows_multiple_answers"
const val isAnonymousField = "is_anonymous"
const val loginUrlField = "login_url"
const val forwardTextField = "forward_text"
const val botUsernameField = "bot_username"
@@ -99,6 +106,11 @@ const val isAnimatedField = "is_animated"
const val inviteLinkField = "invite_link"
const val pinnedMessageField = "pinned_message"
const val customTitleField = "custom_title"
const val optionIdsField = "option_ids"
const val requestContactField = "request_contact"
const val requestLocationField = "request_location"
const val requestPollField = "request_poll"
const val requestWriteAccessField = "request_write_access"
@@ -173,6 +185,7 @@ const val pngStickerField = "png_sticker"
const val okField = "ok"
const val captionField = "caption"
const val idField = "id"
const val pollIdField = "poll_id"
const val textField = "text"
const val thumbField = "thumb"
const val emojiField = "emoji"
@@ -273,3 +286,6 @@ const val mediaField = "media"
const val disableEditMessageField = "disable_edit_message"
const val scoreField = "score"
const val forceField = "force"
const val regularPollType = "regular"
const val quizPollType = "quiz"

View File

@@ -13,7 +13,8 @@ internal data class RawMessageEntity(
val offset: Int,
val length: Int,
val url: String? = null,
val user: User? = null
val user: User? = null,
val language: String? = null
)
internal fun RawMessageEntity.asTextParts(source: String, subParts: List<TextPart>): List<TextPart> {
@@ -23,7 +24,7 @@ internal fun RawMessageEntity.asTextParts(source: String, subParts: List<TextPar
return when (type) {
"mention" -> MentionTextSource(sourceSubstring, shiftedSubParts)
"hashtag" -> HashTagTextSource(sourceSubstring, shiftedSubParts)
"cashtag" -> TODO()
"cashtag" -> CashTagTextSource(sourceSubstring, shiftedSubParts)
"bot_command" -> BotCommandTextSource(sourceSubstring, shiftedSubParts)
"url" -> URLTextSource(sourceSubstring)
"email" -> EMailTextSource(sourceSubstring, shiftedSubParts)
@@ -31,7 +32,7 @@ internal fun RawMessageEntity.asTextParts(source: String, subParts: List<TextPar
"bold" -> BoldTextSource(sourceSubstring, shiftedSubParts)
"italic" -> ItalicTextSource(sourceSubstring, shiftedSubParts)
"code" -> CodeTextSource(sourceSubstring)
"pre" -> PreTextSource(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"), shiftedSubParts)
"underline" -> UnderlineTextSource(sourceSubstring, shiftedSubParts)

View File

@@ -0,0 +1,15 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.MultilevelTextSource
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextPart
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
class CashTagTextSource(
source: String,
textParts: List<TextPart>
) : MultilevelTextSource {
override val textParts: List<TextPart> by lazy { source.fullListOfSubSource(textParts) }
override val asMarkdownSource: String by lazy { source.cashTagMarkdown() }
override val asMarkdownV2Source: String by lazy { cashTagMarkdownV2() }
override val asHtmlSource: String by lazy { cashTagHTML() }
}

View File

@@ -10,6 +10,7 @@ const val UPDATE_CALLBACK_QUERY = "callback_query"
const val UPDATE_SHIPPING_QUERY = "shipping_query"
const val UPDATE_PRE_CHECKOUT_QUERY = "pre_checkout_query"
const val UPDATE_POLL = "poll"
const val UPDATE_POLL_ANSWER = "poll_answer"
val ALL_UPDATES_LIST = listOf(
UPDATE_MESSAGE,
@@ -21,5 +22,6 @@ val ALL_UPDATES_LIST = listOf(
UPDATE_CALLBACK_QUERY,
UPDATE_SHIPPING_QUERY,
UPDATE_PRE_CHECKOUT_QUERY,
UPDATE_POLL
UPDATE_POLL,
UPDATE_POLL_ANSWER
)

View File

@@ -1,14 +1,16 @@
package com.github.insanusmokrassar.TelegramBotAPI.types
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.PrivateChat
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObjectSerializer
@Serializable(UserSerializer::class)
sealed class User : PrivateChat
@Serializable
data class User(
data class CommonUser(
override val id: ChatId,
@SerialName(isBotField)
val isBot: Boolean = false,
@SerialName(firstNameField)
override val firstName: String,
@SerialName(lastNameField)
@@ -17,4 +19,80 @@ data class User(
override val username: Username? = null,
@SerialName(languageCodeField)
val languageCode: String? = null
) : PrivateChat
) : User()
@Serializable(UserSerializer::class)
sealed class Bot : User()
@Serializable
data class CommonBot(
override val id: ChatId,
@SerialName(firstNameField)
override val firstName: String,
@SerialName(lastNameField)
override val lastName: String = "",
@SerialName(usernameField)
override val username: Username? = null
) : Bot() {
@SerialName(isBotField)
private val isBot = true
}
@Serializable
data class ExtendedBot(
override val id: ChatId,
@SerialName(firstNameField)
override val firstName: String,
@SerialName(lastNameField)
override val lastName: String = "",
@SerialName(usernameField)
override val username: Username? = null,
@SerialName(canJoinGroupsField)
val canJoinGroups: Boolean = false,
@SerialName(canReadAllGroupMessagesField)
val canReadAllGroupMessages: Boolean = false,
@SerialName(supportInlineQueriesField)
val supportsInlineQueries: Boolean = false
) : Bot() {
@SerialName(isBotField)
private val isBot = true
}
@Serializer(User::class)
internal object UserSerializer : KSerializer<User> {
override fun deserialize(decoder: Decoder): User {
val asJson = JsonObjectSerializer.deserialize(decoder)
return when {
asJson.getPrimitiveOrNull(isBotField) ?.booleanOrNull != true -> Json.nonstrict.fromJson(
CommonUser.serializer(),
asJson
)
else -> {
if ((asJson.get(canJoinGroupsField)
?: asJson.get(canReadAllGroupMessagesField)
?: asJson.get(supportInlineQueriesField)) != null
) {
Json.nonstrict.fromJson(
ExtendedBot.serializer(),
asJson
)
} else {
Json.nonstrict.fromJson(
CommonBot.serializer(),
asJson
)
}
}
}
}
override fun serialize(encoder: Encoder, obj: User) {
when (obj) {
is CommonUser -> CommonUser.serializer().serialize(encoder, obj)
is CommonBot -> CommonBot.serializer().serialize(encoder, obj)
is ExtendedBot -> ExtendedBot.serializer().serialize(encoder, obj)
}
}
}

View File

@@ -1,13 +1,88 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.buttons
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import kotlinx.serialization.*
import kotlinx.serialization.internal.StringDescriptor
import kotlinx.serialization.json.*
@Serializable(KeyboardButtonSerializer::class)
sealed class KeyboardButton {
abstract val text: String
}
@Serializable
data class KeyboardButton(
val text: String,
@SerialName("request_contact")
val requestContact: Boolean? = null,
@SerialName("request_location")
val requestLocation: Boolean? = null
)
data class SimpleKeyboardButton(
override val text: String
) : KeyboardButton()
@Serializable
data class UnknownKeyboardButton internal constructor(
override val text: String,
val raw: String
) : KeyboardButton()
@Serializable
data class RequestContactKeyboardButton(
override val text: String
) : KeyboardButton() {
@SerialName(requestContactField)
val requestContact: Boolean = true
}
@Serializable
data class RequestLocationKeyboardButton(
override val text: String
) : KeyboardButton() {
@SerialName(requestLocationField)
val requestLocation: Boolean = true
}
@Serializable
data class RequestPollKeyboardButton(
override val text: String,
@SerialName(requestPollField)
val requestPoll: KeyboardButtonPollType
) : KeyboardButton()
@Serializer(KeyboardButton::class)
internal object KeyboardButtonSerializer : KSerializer<KeyboardButton> {
override fun deserialize(decoder: Decoder): KeyboardButton {
val asJson = JsonElementSerializer.deserialize(decoder)
return when {
asJson is JsonPrimitive -> SimpleKeyboardButton(asJson.content)
asJson is JsonObject && asJson.getPrimitiveOrNull(requestContactField) != null -> RequestContactKeyboardButton(
asJson.getPrimitive(textField).content
)
asJson is JsonObject && asJson.getPrimitiveOrNull(requestLocationField) != null -> RequestLocationKeyboardButton(
asJson.getPrimitive(textField).content
)
asJson is JsonObject && asJson.getObjectOrNull(requestPollField) != null -> RequestPollKeyboardButton(
asJson.getPrimitive(textField).content,
Json.nonstrict.fromJson(
KeyboardButtonPollType.serializer(),
asJson.getObject(requestPollField)
)
)
else -> UnknownKeyboardButton(
when (asJson) {
is JsonObject -> asJson.getPrimitive(textField).content
is JsonArray -> ""
is JsonPrimitive -> asJson.content
},
asJson.toString()
)
}
}
override fun serialize(encoder: Encoder, obj: KeyboardButton) {
when (obj) {
is RequestContactKeyboardButton -> RequestContactKeyboardButton.serializer().serialize(encoder, obj)
is RequestLocationKeyboardButton -> RequestLocationKeyboardButton.serializer().serialize(encoder, obj)
is RequestPollKeyboardButton -> RequestPollKeyboardButton.serializer().serialize(encoder, obj)
is SimpleKeyboardButton -> encoder.encodeString(obj.text)
is UnknownKeyboardButton -> JsonElementSerializer.serialize(encoder, Json.nonstrict.parseJson(obj.raw))
}
}
}

View File

@@ -0,0 +1,55 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.buttons
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable(KeyboardButtonPollTypeSerializer::class)
sealed class KeyboardButtonPollType {
abstract val type: String
}
@Serializable
class UnknownKeyboardButtonPollType internal constructor(override val type: String): KeyboardButtonPollType()
@Serializable
object RegularKeyboardButtonPollType : KeyboardButtonPollType() {
override val type: String = regularPollType
}
@Serializable
object QuizKeyboardButtonPollType : KeyboardButtonPollType() {
override val type: String = quizPollType
}
@Serializer(KeyboardButtonPollType::class)
internal object KeyboardButtonPollTypeSerializer : KSerializer<KeyboardButtonPollType> {
override fun deserialize(decoder: Decoder): KeyboardButtonPollType {
val asJson = JsonElementSerializer.deserialize(decoder)
val type = when (asJson) {
is JsonPrimitive -> asJson.content
else -> asJson.jsonObject.getPrimitive(typeField).content
}
return when (type) {
regularPollType -> RegularKeyboardButtonPollType
quizPollType -> QuizKeyboardButtonPollType
else -> UnknownKeyboardButtonPollType(type)
}
}
/**
* Crutch due to the fact that direct serialization of objects currently does not work perfectly
*/
override fun serialize(encoder: Encoder, obj: KeyboardButtonPollType) {
JsonObjectSerializer.serialize(
encoder,
JsonObject(
mapOf(
typeField to JsonPrimitive(obj.type)
)
)
)
}
}

View File

@@ -1,10 +1,12 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.chat
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.UnknownChatType
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.extended.*
import com.github.insanusmokrassar.TelegramBotAPI.types.typeField
import kotlinx.serialization.*
import kotlinx.serialization.internal.LongSerializer
import kotlinx.serialization.internal.StringDescriptor
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObjectSerializer
@@ -24,7 +26,10 @@ internal object PreviewChatSerializer : KSerializer<Chat> {
"group" -> formatter.fromJson(GroupChatImpl.serializer(), decodedJson)
"supergroup" -> formatter.fromJson(SupergroupChatImpl.serializer(), decodedJson)
"channel" -> formatter.fromJson(ChannelChatImpl.serializer(), decodedJson)
else -> throw IllegalArgumentException("Unknown type of chat")
else -> UnknownChatType(
formatter.fromJson(LongSerializer, decodedJson.getPrimitive(chatIdField)).toChatId(),
decodedJson.toString()
)
}
}

View File

@@ -7,4 +7,9 @@ import kotlinx.serialization.Serializable
@Serializable(PreviewChatSerializer::class)
interface Chat {
val id: ChatId
}
}
data class UnknownChatType(
override val id: ChatId,
val raw: String
) : Chat

View File

@@ -10,6 +10,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.games.RawGame
import com.github.insanusmokrassar.TelegramBotAPI.types.message.ChatEvents.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.ChatEvents.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.UnknownMessageType
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.*
@@ -184,91 +185,99 @@ internal data class RawMessage(
val asMessage: Message by lazy {
chatEvent ?.let {
chatEvent ->
when (chat) {
is SupergroupChat -> SupergroupEventMessage(
messageId,
chat,
chatEvent as? SupergroupEvent ?: throwWrongChatEvent(SupergroupEvent::class, chatEvent),
date.asDate
)
is GroupChat -> GroupEventMessage(
messageId,
chat,
chatEvent as? GroupEvent ?: throwWrongChatEvent(GroupChat::class, chatEvent),
date.asDate
)
is ChannelChat -> ChannelEventMessage(
messageId,
chat,
chatEvent as? ChannelEvent ?: throwWrongChatEvent(ChannelEvent::class, chatEvent),
date.asDate
)
else -> throw IllegalStateException("Expected one of the public chats, but was $chat (in extracting of chat event message)")
}
} ?: content ?.let {
content ->
media_group_id ?.let {
when (from) {
null -> ChannelMediaGroupMessage(
try {
chatEvent?.let { chatEvent ->
when (chat) {
is SupergroupChat -> SupergroupEventMessage(
messageId,
chat,
date.asDate,
it,
when (content) {
is PhotoContent -> content
is VideoContent -> content
else -> throw IllegalStateException("Unsupported content for media group")
},
edit_date ?.asDate,
forwarded,
reply_to_message ?.asMessage,
reply_markup
chatEvent as? SupergroupEvent ?: throwWrongChatEvent(SupergroupEvent::class, chatEvent),
date.asDate
)
else -> CommonMediaGroupMessage(
is GroupChat -> GroupEventMessage(
messageId,
from,
chat,
chatEvent as? GroupEvent ?: throwWrongChatEvent(GroupChat::class, chatEvent),
date.asDate
)
is ChannelChat -> ChannelEventMessage(
messageId,
chat,
chatEvent as? ChannelEvent ?: throwWrongChatEvent(ChannelEvent::class, chatEvent),
date.asDate
)
else -> throw IllegalStateException("Expected one of the public chats, but was $chat (in extracting of chat event message)")
}
} ?: content?.let { content ->
media_group_id?.let {
when (from) {
null -> ChannelMediaGroupMessage(
messageId,
chat,
date.asDate,
it,
when (content) {
is PhotoContent -> content
is VideoContent -> content
else -> throw IllegalStateException("Unsupported content for media group")
},
edit_date?.asDate,
forwarded,
reply_to_message?.asMessage,
reply_markup
)
else -> CommonMediaGroupMessage(
messageId,
from,
chat,
date.asDate,
it,
when (content) {
is PhotoContent -> content
is VideoContent -> content
else -> throw IllegalStateException("Unsupported content for media group")
},
edit_date?.asDate,
forwarded,
reply_to_message?.asMessage,
reply_markup
)
}
} ?: when (chat) {
is ChannelChat -> ChannelMessage(
messageId,
chat,
content,
date.asDate,
it,
when (content) {
is PhotoContent -> content
is VideoContent -> content
else -> throw IllegalStateException("Unsupported content for media group")
},
edit_date ?.asDate,
edit_date?.asDate,
forwarded,
reply_to_message ?.asMessage,
reply_markup
reply_to_message?.asMessage,
reply_markup,
author_signature
)
else -> CommonMessageImpl(
messageId,
from
?: throw IllegalStateException("Was detected common message, but owner (sender) of the message was not found"),
chat,
content,
date.asDate,
edit_date?.asDate,
forwarded,
reply_to_message?.asMessage,
reply_markup,
paymentInfo
)
}
} ?: when (chat) {
is ChannelChat -> ChannelMessage(
messageId,
chat,
content,
date.asDate,
edit_date ?.asDate,
forwarded,
reply_to_message ?.asMessage,
reply_markup,
author_signature
)
else -> CommonMessageImpl(
messageId,
from ?: throw IllegalStateException("Was detected common message, but owner (sender) of the message was not found"),
chat,
content,
date.asDate,
edit_date ?.asDate,
forwarded,
reply_to_message ?.asMessage,
reply_markup,
paymentInfo
)
}
} ?: throw IllegalStateException("Was not found supported type of data")
} ?: throw IllegalStateException("Was not found supported type of data")
} catch (e: Exception) {
UnknownMessageType(
messageId,
chat,
date.asDate,
e
)
}
}
private fun throwWrongChatEvent(expected: KClass<*>, but: ChatEvent): CommonEvent {

View File

@@ -13,6 +13,13 @@ interface Message {
val date: DateTime
}
data class UnknownMessageType(
override val messageId: MessageIdentifier,
override val chat: Chat,
override val date: DateTime,
val insideException: Exception
) : Message
internal class TelegramBotAPIMessageDeserializationStrategyClass<T> : DeserializationStrategy<T> {
override val descriptor: SerialDescriptor = StringDescriptor.withName("TelegramBotAPIMessageSerializer")

View File

@@ -5,7 +5,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendContact
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
data class ContactContent(

View File

@@ -7,7 +7,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.games.Game
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
data class GameContent(

View File

@@ -5,7 +5,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendLocation
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
data class LocationContent(

View File

@@ -1,14 +1,15 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.message.content
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendPoll
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.polls.SendPoll
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.polls.createRequest
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.Poll
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.RegularPoll
data class PollContent(
val poll: Poll
@@ -18,10 +19,8 @@ data class PollContent(
disableNotification: Boolean,
replyToMessageId: MessageIdentifier?,
replyMarkup: KeyboardMarkup?
): Request<ContentMessage<PollContent>> = SendPoll(
): Request<ContentMessage<PollContent>> = poll.createRequest(
chatId,
poll.question,
poll.options.map { it.text },
disableNotification,
replyToMessageId,
replyMarkup

View File

@@ -2,14 +2,12 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.message.content
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextPart
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendMessage
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendTextMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.*

View File

@@ -5,7 +5,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendVenue
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
data class VenueContent(

View File

@@ -1,7 +1,9 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMedia
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.TelegramMediaFile
interface MediaContent: MessageContent {
val media: TelegramMediaFile
fun asInputMedia(): InputMedia
}

View File

@@ -5,15 +5,17 @@ import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextPart
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendAnimation
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaAnimation
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.HTMLParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.MarkdownV2
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.AnimationFile
import com.github.insanusmokrassar.TelegramBotAPI.types.files.DocumentFile
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.toHtmlCaptions
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownV2Captions
data class AnimationContent(
override val media: AnimationFile,
@@ -39,4 +41,14 @@ data class AnimationContent(
replyToMessageId,
replyMarkup
)
}
override fun asInputMedia(): InputMediaAnimation = InputMediaAnimation(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
media.width,
media.height,
media.duration,
media.thumb ?.fileId
)
}

View File

@@ -5,14 +5,16 @@ import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextPart
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendAudio
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaAudio
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.HTMLParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.MarkdownV2
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.AudioFile
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.toHtmlCaptions
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownV2Captions
data class AudioContent(
override val media: AudioFile,
@@ -37,4 +39,14 @@ data class AudioContent(
replyToMessageId,
replyMarkup
)
override fun asInputMedia(): InputMediaAudio = InputMediaAudio(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
media.duration,
media.performer,
media.title,
media.thumb ?.fileId
)
}

View File

@@ -5,14 +5,16 @@ import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextPart
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendDocument
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaDocument
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.HTMLParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.MarkdownV2
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.DocumentFile
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.toHtmlCaptions
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownV2Captions
data class DocumentContent(
override val media: DocumentFile,
@@ -34,4 +36,11 @@ data class DocumentContent(
replyToMessageId,
replyMarkup
)
override fun asInputMedia(): InputMediaDocument = InputMediaDocument(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
media.thumb ?.fileId
)
}

View File

@@ -8,14 +8,15 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaPho
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.MediaGroupMemberInputMedia
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.HTMLParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.MarkdownV2
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.PhotoSize
import com.github.insanusmokrassar.TelegramBotAPI.types.files.biggest
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaCollectionContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaGroupContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.toHtmlCaptions
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownV2Captions
data class PhotoContent(
override val mediaCollection: List<PhotoSize>,
@@ -44,4 +45,10 @@ data class PhotoContent(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaPhoto = InputMediaPhoto(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2
)
}

View File

@@ -3,11 +3,11 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendSticker
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaDocument
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.Sticker
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
data class StickerContent(
@@ -25,4 +25,10 @@ data class StickerContent(
replyToMessageId,
replyMarkup
)
override fun asInputMedia(): InputMediaDocument = InputMediaDocument(
media.fileId,
null,
thumb = media.thumb ?.fileId
)
}

View File

@@ -8,12 +8,13 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaVid
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.MediaGroupMemberInputMedia
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.HTMLParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.MarkdownV2
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.VideoFile
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaGroupContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.toHtmlCaptions
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownV2Captions
data class VideoContent(
override val media: VideoFile,
@@ -49,4 +50,14 @@ data class VideoContent(
media.duration,
media.thumb ?.fileId
)
override fun asInputMedia(): InputMediaVideo = InputMediaVideo(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
media.width,
media.height,
media.duration,
media.thumb ?.fileId
)
}

View File

@@ -3,12 +3,12 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendVideoNote
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaVideo
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.VideoNoteFile
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
data class VideoNoteContent(
@@ -40,4 +40,12 @@ data class VideoNoteContent(
replyToMessageId,
replyMarkup
)
override fun asInputMedia(): InputMediaVideo = InputMediaVideo(
media.fileId,
width = media.width,
height = media.height,
duration = media.duration,
thumb = media.thumb ?.fileId
)
}

View File

@@ -5,14 +5,16 @@ import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextPart
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendVoice
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.InputMediaAudio
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.HTMLParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.MarkdownV2
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.files.VoiceFile
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.toHtmlCaptions
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownV2Captions
data class VoiceContent(
override val media: VoiceFile,
@@ -35,4 +37,11 @@ data class VoiceContent(
replyToMessageId,
replyMarkup
)
override fun asInputMedia(): InputMediaAudio = InputMediaAudio(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
media.duration
)
}

View File

@@ -1,17 +1,119 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.polls
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.*
import kotlinx.serialization.internal.ArrayListSerializer
import kotlinx.serialization.json.*
@Serializable(PollSerializer::class)
sealed class Poll {
abstract val id: PollIdentifier
abstract val question: String
abstract val options: List<PollOption>
abstract val votesCount: Int
abstract val isClosed: Boolean
abstract val isAnonymous: Boolean
}
@Serializable
data class Poll(
data class UnknownPollType internal constructor(
@SerialName(idField)
val id: PollIdentifier,
override val id: PollIdentifier,
@SerialName(questionField)
val question: String,
override val question: String,
@SerialName(optionsField)
val options: List<PollOption>,
override val options: List<PollOption>,
@SerialName(totalVoterCountField)
override val votesCount: Int,
@SerialName(isClosedField)
val closed: Boolean = false
)
override val isClosed: Boolean = false,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = false,
val raw: String
) : Poll()
@Serializable
data class RegularPoll(
@SerialName(idField)
override val id: PollIdentifier,
@SerialName(questionField)
override val question: String,
@SerialName(optionsField)
override val options: List<PollOption>,
@SerialName(totalVoterCountField)
override val votesCount: Int,
@SerialName(isClosedField)
override val isClosed: Boolean = false,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = false,
@SerialName(allowsMultipleAnswersField)
val allowMultipleAnswers: Boolean = false
) : Poll()
@Serializable
data class QuizPoll(
@SerialName(idField)
override val id: PollIdentifier,
@SerialName(questionField)
override val question: String,
@SerialName(optionsField)
override val options: List<PollOption>,
@SerialName(totalVoterCountField)
override val votesCount: Int,
/**
* Nullable due to documentation (https://core.telegram.org/bots/api#poll)
*/
@SerialName(correctOptionIdField)
val correctOptionId: Int? = null,
@SerialName(isClosedField)
override val isClosed: Boolean = false,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = false
) : Poll()
@Serializer(Poll::class)
internal object PollSerializer : KSerializer<Poll> {
private val pollOptionsSerializer = ArrayListSerializer(PollOption.serializer())
override fun deserialize(decoder: Decoder): Poll {
val asJson = JsonObjectSerializer.deserialize(decoder)
return when (asJson.getPrimitive(typeField).content) {
regularPollType -> Json.nonstrict.fromJson(
RegularPoll.serializer(),
asJson
)
quizPollType -> Json.nonstrict.fromJson(
QuizPoll.serializer(),
asJson
)
else -> UnknownPollType(
asJson.getPrimitive(idField).content,
asJson.getPrimitive(questionField).content,
Json.nonstrict.fromJson(
pollOptionsSerializer,
asJson.getArray(optionsField)
),
asJson.getPrimitive(totalVoterCountField).int,
asJson.getPrimitiveOrNull(isClosedField) ?.booleanOrNull ?: false,
asJson.getPrimitiveOrNull(isAnonymousField) ?.booleanOrNull ?: true,
asJson.toString()
)
}
}
override fun serialize(encoder: Encoder, obj: Poll) {
val asJson = when (obj) {
is RegularPoll -> Json.nonstrict.toJson(RegularPoll.serializer(), obj)
is QuizPoll -> Json.nonstrict.toJson(QuizPoll.serializer(), obj)
is UnknownPollType -> throw IllegalArgumentException("Currently unable to correctly serialize object of poll $obj")
}
val resultJson = JsonObject(
asJson.jsonObject + (typeField to when (obj) {
is RegularPoll -> JsonPrimitive(regularPollType)
is QuizPoll -> JsonPrimitive(quizPollType)
is UnknownPollType -> throw IllegalArgumentException("Currently unable to correctly serialize object of poll $obj")
})
)
JsonObjectSerializer.serialize(encoder, resultJson)
}
}

View File

@@ -0,0 +1,15 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.polls
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PollAnswer(
@SerialName(pollIdField)
val pollId: PollIdentifier,
@SerialName(userField)
val user: User,
@SerialName(optionIdsField)
val chosen: List<Int>
)

View File

@@ -12,7 +12,7 @@ sealed class PollOption {
}
@Serializable
data class AnonymousPollOption (
data class SimplePollOption (
@SerialName(textField)
override val text: String,
@SerialName(votesCountField)
@@ -22,13 +22,13 @@ data class AnonymousPollOption (
internal object PollOptionSerializer : KSerializer<PollOption> {
override val descriptor: SerialDescriptor = StringDescriptor.withName(PollOption::class.simpleName ?: "PollOption")
override fun deserialize(decoder: Decoder): PollOption = AnonymousPollOption.serializer().deserialize(
override fun deserialize(decoder: Decoder): PollOption = SimplePollOption.serializer().deserialize(
decoder
)
override fun serialize(encoder: Encoder, obj: PollOption) {
when (obj) {
is AnonymousPollOption -> AnonymousPollOption.serializer().serialize(
is SimplePollOption -> SimplePollOption.serializer().serialize(
encoder,
obj
)

View File

@@ -0,0 +1,10 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.update
import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.PollAnswer
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
data class PollAnswerUpdate(
override val updateId: UpdateIdentifier,
override val data: PollAnswer
) : Update

View File

@@ -9,10 +9,13 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Telegr
import com.github.insanusmokrassar.TelegramBotAPI.types.payments.PreCheckoutQuery
import com.github.insanusmokrassar.TelegramBotAPI.types.payments.ShippingQuery
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.Poll
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.PollAnswer
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.UnknownUpdateType
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
import com.github.insanusmokrassar.TelegramBotAPI.types.updateIdField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@Serializable
internal data class RawUpdate constructor(
@@ -31,10 +34,15 @@ internal data class RawUpdate constructor(
private val callback_query: RawCallbackQuery? = null,
private val shipping_query: ShippingQuery? = null,
private val pre_checkout_query: PreCheckoutQuery? = null,
private val poll: Poll? = null
private val poll: Poll? = null,
private val poll_answer: PollAnswer? = null
) {
val asUpdate: Update by lazy {
when {
private var initedUpdate: Update? = null
/**
* @return One of children of [Update] interface or null in case of unknown type of update
*/
fun asUpdate(raw: JsonElement): Update {
return initedUpdate ?: when {
edited_message != null -> EditMessageUpdate(updateId, edited_message)
message != null -> MessageUpdate(updateId, message)
edited_channel_post != null -> EditChannelPostUpdate(updateId, edited_channel_post)
@@ -42,11 +50,20 @@ internal data class RawUpdate constructor(
chosen_inline_result != null -> ChosenInlineResultUpdate(updateId, chosen_inline_result.asChosenInlineResult)
inline_query != null -> InlineQueryUpdate(updateId, inline_query.asInlineQuery)
callback_query != null -> CallbackQueryUpdate(updateId, callback_query.asCallbackQuery)
callback_query != null -> CallbackQueryUpdate(
updateId,
callback_query.asCallbackQuery(raw.jsonObject["callback_query"].toString())
)
shipping_query != null -> ShippingQueryUpdate(updateId, shipping_query)
pre_checkout_query != null -> PreCheckoutQueryUpdate(updateId, pre_checkout_query)
poll != null -> PollUpdate(updateId, poll)
else -> throw IllegalArgumentException("Unsupported type of update")
poll_answer != null -> PollAnswerUpdate(updateId, poll_answer)
else -> UnknownUpdateType(
updateId,
raw.toString()
)
}.also {
initedUpdate = it
}
}
}

View File

@@ -4,12 +4,19 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.update.RawUpdate
import kotlinx.serialization.*
import kotlinx.serialization.internal.StringDescriptor
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElementSerializer
interface Update {
val updateId: UpdateIdentifier
val data: Any
}
data class UnknownUpdateType(
override val updateId: UpdateIdentifier,
override val data: String
) : Update
internal object UpdateSerializerWithoutDeserialization : KSerializer<Update> {
override val descriptor: SerialDescriptor = StringDescriptor.withName("UpdateSerializerWithoutDeserialization")
@@ -24,6 +31,12 @@ internal object UpdateDeserializationStrategy : DeserializationStrategy<Update>
override fun patch(decoder: Decoder, old: Update): Update = throw UpdateNotSupportedException(descriptor.name)
override fun deserialize(decoder: Decoder): Update {
return RawUpdate.serializer().deserialize(decoder).asUpdate
val asJson = JsonElementSerializer.deserialize(decoder)
return Json.nonstrict.fromJson(
RawUpdate.serializer(),
asJson
).asUpdate(
asJson
)
}
}

View File

@@ -3,6 +3,7 @@ package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.UnknownUpdateType
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.UpdateReceiver
@@ -20,7 +21,9 @@ data class UpdatesFilter(
private val callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
private val shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
private val preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
private val pollUpdateCallback: UpdateReceiver<PollUpdate>? = null
private val pollUpdateCallback: UpdateReceiver<PollUpdate>? = null,
private val pollAnswerUpdateCallback: UpdateReceiver<PollAnswerUpdate>? = null,
private val unknownUpdateTypeCallback: UpdateReceiver<UnknownUpdateType>? = null
) {
val asUpdateReceiver: UpdateReceiver<Update> = this::invoke
val allowedUpdates = listOfNotNull(
@@ -33,7 +36,8 @@ data class UpdatesFilter(
callbackQueryCallback ?.let { UPDATE_CALLBACK_QUERY },
shippingQueryCallback ?.let { UPDATE_SHIPPING_QUERY },
preCheckoutQueryCallback ?.let { UPDATE_PRE_CHECKOUT_QUERY },
pollUpdateCallback ?.let { UPDATE_POLL }
pollUpdateCallback ?.let { UPDATE_POLL },
pollAnswerUpdateCallback ?.let { UPDATE_POLL_ANSWER }
)
suspend fun invoke(update: Update) {
@@ -72,6 +76,8 @@ data class UpdatesFilter(
is ShippingQueryUpdate -> shippingQueryCallback ?.invoke(update)
is PreCheckoutQueryUpdate -> preCheckoutQueryCallback ?.invoke(update)
is PollUpdate -> pollUpdateCallback ?.invoke(update)
is PollAnswerUpdate -> pollAnswerUpdateCallback ?.invoke(update)
is UnknownUpdateType -> unknownUpdateTypeCallback ?.invoke(update)
}
}
}
@@ -87,7 +93,9 @@ fun createSimpleUpdateFilter(
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
pollCallback: UpdateReceiver<PollUpdate>? = null
pollCallback: UpdateReceiver<PollUpdate>? = null,
pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null,
unknownCallback: UpdateReceiver<UnknownUpdateType>? = null
): UpdatesFilter = UpdatesFilter(
messageCallback = messageCallback,
messageMediaGroupCallback = mediaGroupCallback,
@@ -102,5 +110,7 @@ fun createSimpleUpdateFilter(
callbackQueryCallback = callbackQueryCallback,
shippingQueryCallback = shippingQueryCallback,
preCheckoutQueryCallback = preCheckoutQueryCallback,
pollUpdateCallback = pollCallback
pollUpdateCallback = pollCallback,
pollAnswerUpdateCallback = pollAnswerCallback,
unknownUpdateTypeCallback = unknownCallback
)

View File

@@ -0,0 +1,6 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
import kotlin.Experimental.Level
@Experimental(Level.WARNING)
annotation class PreviewFeature

View File

@@ -0,0 +1,36 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.PrivateChat
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.UsernameChat
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat
private const val internalLinkBeginning = "https://t.me"
@PreviewFeature
fun makeLinkToMessage(
username: String,
messageId: MessageIdentifier
): String = "$internalLinkBeginning/$username/$messageId"
private val linkIdRedundantPartRegex = Regex("^-100")
private val usernameBeginSymbolRegex = Regex("^@")
@PreviewFeature
fun makeLinkToMessage(
chat: ExtendedChat,
messageId: MessageIdentifier
): String? {
return when {
chat is UsernameChat && chat.username != null -> {
"$internalLinkBeginning/${chat.username ?.username ?.replace(usernameBeginSymbolRegex, "")}/$messageId"
}
chat !is PrivateChat -> chat.id.chatId.toString().replace(
linkIdRedundantPartRegex,
""
).let { bareId ->
"$internalLinkBeginning/c/$bareId/$messageId"
}
else -> return null
}
}

View File

@@ -107,6 +107,10 @@ internal fun MultilevelTextSource.boldMarkdownV2(): String = markdownV2Default(m
internal fun MultilevelTextSource.boldHTML(): String = htmlDefault(htmlBoldControl)
internal fun MultilevelTextSource.cashTagMarkdownV2(): String = textParts.joinSubSourcesMarkdownV2()
internal fun MultilevelTextSource.cashTagHTML(): String = textParts.joinSubSourcesHtml()
internal fun MultilevelTextSource.italicMarkdownV2(): String = markdownV2Default(markdownItalicControl)
internal fun MultilevelTextSource.italicHTML(): String = htmlDefault(htmlItalicControl)

View File

@@ -145,6 +145,11 @@ fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
fun String.regularHtml(): String = toHtml()
fun String.cashTagMarkdown(): String = toMarkdown()
fun String.cashTagMarkdownV2(): String = escapeMarkdownV2Common()
fun String.cashTagHtml(): String = toHtml()
infix fun String.bold(parseMode: ParseMode): String = when (parseMode) {
is HTML -> boldHTML()
is Markdown -> boldMarkdown()
@@ -230,3 +235,9 @@ infix fun String.regular(parseMode: ParseMode): String = when (parseMode) {
is Markdown -> regularMarkdown()
is MarkdownV2 -> regularMarkdownV2()
}
infix fun String.cashtag(parseMode: ParseMode): String = when (parseMode) {
is HTML -> cashTagHtml()
is Markdown -> cashTagMarkdown()
is MarkdownV2 -> cashTagMarkdownV2()
}

View File

@@ -43,6 +43,7 @@ fun RequestsExecutor.startGettingOfUpdates(
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
pollCallback: UpdateReceiver<PollUpdate>? = null,
pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null,
timeoutMillis: Long = 30 * 1000,
scope: CoroutineScope = GlobalScope
): UpdatesPoller {
@@ -60,7 +61,8 @@ fun RequestsExecutor.startGettingOfUpdates(
callbackQueryCallback,
shippingQueryCallback,
preCheckoutQueryCallback,
pollCallback
pollCallback,
pollAnswerCallback
)
return startGettingOfUpdates(
timeoutMillis,
@@ -82,6 +84,7 @@ fun RequestsExecutor.startGettingOfUpdates(
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
pollCallback: UpdateReceiver<PollUpdate>? = null,
pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null,
timeoutMillis: Long = 30 * 1000,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
): UpdatesPoller = startGettingOfUpdates(
@@ -99,6 +102,7 @@ fun RequestsExecutor.startGettingOfUpdates(
shippingQueryCallback = shippingQueryCallback,
preCheckoutQueryCallback = preCheckoutQueryCallback,
pollCallback = pollCallback,
pollAnswerCallback = pollAnswerCallback,
timeoutMillis = timeoutMillis,
scope = scope
)

View File

@@ -2,6 +2,6 @@ package com.github.insanusmokrassar.TelegramBotAPI.types
import java.util.*
fun User.javaLocale(): Locale? = languageCode ?.let {
fun CommonUser.javaLocale(): Locale? = languageCode ?.let {
Locale.forLanguageTag(it)
}

View File

@@ -73,12 +73,12 @@ suspend fun RequestsExecutor.setWebhook(
module {
routing {
post(listenRoute) {
val deserialized = call.receiveText()
val update = Json.nonstrict.parse(
val asJson = Json.nonstrict.parseJson(call.receiveText())
val update = Json.nonstrict.fromJson(
RawUpdate.serializer(),
deserialized
asJson
)
updatesChannel.send(update.asUpdate)
updatesChannel.send(update.asUpdate(asJson))
call.respond("Ok")
}
}