mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-11-17 20:40:20 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99f16e33a6 | |||
| e029b29f7f | |||
| c04f795fdd | |||
| b873898100 | |||
| 61ac9df5e3 | |||
| b1931900e7 | |||
| fab3af48d6 | |||
| 8d7563b6e4 | |||
| 05112afe0c | |||
| 9ea06de27c | |||
| fff05a40d9 | |||
| 5c6428f220 | |||
| 766b7ca205 | |||
| 41e6c52369 | |||
| 06013f624f | |||
| d8bba89f3f | |||
| 141281f96d | |||
| be7aaa7845 | |||
| 78c224ffa8 | |||
| a08d07f7b3 | |||
| 69dde19543 | |||
| e8a3b93831 | |||
| e10caa3171 | |||
| d4fe4e09fc | |||
| ad453afba2 | |||
| a0daca28b1 | |||
| cd62a9ef3c | |||
| 3c084d70e5 | |||
| 2611d4ecc1 | |||
| b4d853dfa0 | |||
| 5044075adf | |||
| 5f2660b804 | |||
| c72dccc0f9 | |||
| 3fc1058491 | |||
| c3668e978b | |||
| 5a4a6d5710 | |||
| ed1d8beb2e | |||
| 881ede7d2a | |||
| 60d3d279e7 | |||
| 4b84518dbb |
30
CHANGELOG.md
30
CHANGELOG.md
@@ -1,5 +1,35 @@
|
|||||||
# TelegramBotAPI changelog
|
# TelegramBotAPI changelog
|
||||||
|
|
||||||
|
## 3.2.0
|
||||||
|
|
||||||
|
**Since this update, `RequestsExecutor#execute` may throw only `BotException`. In case you wish to handle some exceptions from `execute` you must catch `BotException` and handle its `cause`**
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Serialization`: `1.4.0-RC` -> `1.4.0`
|
||||||
|
* `MicroUtils`: `0.12.1` -> `0.12.4`
|
||||||
|
* `Core`:
|
||||||
|
* `SetWebhook#allowedUpdates` now is `ALL_UPDATES_LIST` by default instead of `null`
|
||||||
|
* `API`:
|
||||||
|
* Extension `TelegramBot#setWebhook` parameter `allowedUpdates` now is `ALL_UPDATES_LIST` by default instead of `null`
|
||||||
|
* `Utils`:
|
||||||
|
* All related to long polling extensions parameters `allowedUpdates` now are `ALL_UPDATES_LIST` by default instead of `null`
|
||||||
|
|
||||||
|
## 3.1.1
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* Complete Bot API 6.2 implementation
|
||||||
|
|
||||||
|
## 3.1.0
|
||||||
|
|
||||||
|
**This update contains including of Bot API 6.2**
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Ktor`: `2.0.3` -> `2.1.0`
|
||||||
|
* `MicroUtils`: `0.12.0` -> `0.12.1`
|
||||||
|
* `Core`:
|
||||||
|
* Add support of `custom emoji`s
|
||||||
|
* Add support of `sticker_type`
|
||||||
|
|
||||||
## 3.0.2
|
## 3.0.2
|
||||||
|
|
||||||
**ALL OLD DEPRECATIONS HAVE BEEN REMOVED**
|
**ALL OLD DEPRECATIONS HAVE BEEN REMOVED**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# TelegramBotAPI [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [](https://core.telegram.org/bots/api-changelog#june-20-2022)
|
# TelegramBotAPI [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [](https://core.telegram.org/bots/api-changelog#august-12-2022)
|
||||||
|
|
||||||
| Docs | [](https://tgbotapi.inmo.dev/index.html) [](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
| Docs | [](https://tgbotapi.inmo.dev/index.html) [](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
||||||
|:---:|:---:|
|
|:---:|:---:|
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ kotlin.incremental=true
|
|||||||
kotlin.incremental.js=true
|
kotlin.incremental.js=true
|
||||||
|
|
||||||
library_group=dev.inmo
|
library_group=dev.inmo
|
||||||
library_version=3.0.2
|
library_version=3.2.0
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kotlin = "1.7.10"
|
kotlin = "1.7.10"
|
||||||
kotlin-serialization = "1.4.0-RC"
|
kotlin-serialization = "1.4.0"
|
||||||
kotlin-coroutines = "1.6.4"
|
kotlin-coroutines = "1.6.4"
|
||||||
|
|
||||||
javax-activation = "1.1.1"
|
javax-activation = "1.1.1"
|
||||||
|
|
||||||
korlibs = "3.0.0"
|
korlibs = "3.0.0"
|
||||||
uuid = "0.5.0"
|
uuid = "0.5.0"
|
||||||
ktor = "2.0.3"
|
ktor = "2.1.0"
|
||||||
|
|
||||||
ksp = "1.7.10-1.0.6"
|
ksp = "1.7.10-1.0.6"
|
||||||
kotlin-poet = "1.12.0"
|
kotlin-poet = "1.12.0"
|
||||||
|
|
||||||
microutils = "0.12.0"
|
microutils = "0.12.4"
|
||||||
|
|
||||||
github-release-plugin = "2.4.1"
|
github-release-plugin = "2.4.1"
|
||||||
|
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.get
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.get.GetCustomEmojiStickers
|
||||||
|
import dev.inmo.tgbotapi.requests.get.GetStickerSet
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
|
import dev.inmo.tgbotapi.types.files.Sticker
|
||||||
|
import kotlin.js.JsName
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
|
||||||
|
suspend fun TelegramBot.getCustomEmojiStickers(
|
||||||
|
customEmojiIds: List<CustomEmojiId>
|
||||||
|
) = execute(
|
||||||
|
GetCustomEmojiStickers(customEmojiIds)
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmName("getCustomEmojiStickersWithStringsList")
|
||||||
|
@JsName("getCustomEmojiStickersWithStringsList")
|
||||||
|
suspend fun TelegramBot.getCustomEmojiStickers(
|
||||||
|
customEmojiIds: List<String>
|
||||||
|
) = getCustomEmojiStickers(customEmojiIds.map(::CustomEmojiId))
|
||||||
|
|
||||||
|
suspend fun TelegramBot.getCustomEmojiStickerOrNull(
|
||||||
|
customEmojiId: CustomEmojiId
|
||||||
|
) = getCustomEmojiStickers(listOf(customEmojiId)).firstOrNull()
|
||||||
|
|
||||||
|
suspend fun TelegramBot.getCustomEmojiStickerOrThrow(
|
||||||
|
customEmojiId: CustomEmojiId
|
||||||
|
) = getCustomEmojiStickers(listOf(customEmojiId)).first()
|
||||||
|
|
||||||
|
suspend fun TelegramBot.getCustomEmojiStickerOrNull(
|
||||||
|
customEmojiId: String
|
||||||
|
) = getCustomEmojiStickerOrNull(CustomEmojiId(customEmojiId))
|
||||||
|
|
||||||
|
suspend fun TelegramBot.getCustomEmojiStickerOrThrow(
|
||||||
|
customEmojiId: String
|
||||||
|
) = getCustomEmojiStickerOrThrow(CustomEmojiId(customEmojiId))
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = execute(
|
||||||
|
CreateNewMaskAnimatedStickerSet(userId, name, title, sticker, emojis, maskPosition)
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = execute(
|
||||||
|
CreateNewMaskAnimatedStickerSet(userId, name, title, sticker, emojis, maskPosition)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = createNewMaskAnimatedStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis, maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = createNewMaskAnimatedStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis, maskPosition
|
||||||
|
)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = execute(
|
||||||
|
CreateNewMaskStickerSet(userId, name, title, sticker, emojis, maskPosition)
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = execute(
|
||||||
|
CreateNewMaskStickerSet(userId, name, title, sticker, emojis, maskPosition)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = createNewMaskStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis, maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = createNewMaskStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis, maskPosition
|
||||||
|
)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = execute(
|
||||||
|
CreateNewMaskVideoStickerSet(userId, name, title, sticker, emojis, maskPosition)
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = execute(
|
||||||
|
CreateNewMaskVideoStickerSet(userId, name, title, sticker, emojis, maskPosition)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskVideoStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = createNewMaskVideoStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis, maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewMaskVideoStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
) = createNewMaskVideoStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis, maskPosition
|
||||||
|
)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String
|
||||||
|
) = execute(
|
||||||
|
CreateNewRegularAnimatedStickerSet(userId, name, title, sticker, emojis)
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String
|
||||||
|
) = execute(
|
||||||
|
CreateNewRegularAnimatedStickerSet(userId, name, title, sticker, emojis)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String
|
||||||
|
) = createNewRegularAnimatedStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String
|
||||||
|
) = createNewRegularAnimatedStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis
|
||||||
|
)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String
|
||||||
|
) = execute(
|
||||||
|
CreateNewRegularStickerSet(userId, name, title, sticker, emojis)
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String
|
||||||
|
) = execute(
|
||||||
|
CreateNewRegularStickerSet(userId, name, title, sticker, emojis)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String
|
||||||
|
) = createNewRegularStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String
|
||||||
|
) = createNewRegularStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis
|
||||||
|
)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String
|
||||||
|
) = execute(
|
||||||
|
CreateNewRegularVideoStickerSet(userId, name, title, sticker, emojis)
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String
|
||||||
|
) = execute(
|
||||||
|
CreateNewRegularVideoStickerSet(userId, name, title, sticker, emojis)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularVideoStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: FileId,
|
||||||
|
emojis: String
|
||||||
|
) = createNewRegularVideoStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun TelegramBot.createNewRegularVideoStickerSet(
|
||||||
|
user: CommonUser,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: MultipartFile,
|
||||||
|
emojis: String
|
||||||
|
) = createNewRegularVideoStickerSet(
|
||||||
|
user.id, name, title, sticker, emojis
|
||||||
|
)
|
||||||
@@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.bot.TelegramBot
|
|||||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
||||||
import dev.inmo.tgbotapi.requests.webhook.SetWebhook
|
import dev.inmo.tgbotapi.requests.webhook.SetWebhook
|
||||||
|
import dev.inmo.tgbotapi.types.ALL_UPDATES_LIST
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this method to send information about webhook (like [url])
|
* Use this method to send information about webhook (like [url])
|
||||||
@@ -12,7 +13,7 @@ suspend fun TelegramBot.setWebhookInfo(
|
|||||||
url: String,
|
url: String,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
) = execute(
|
) = execute(
|
||||||
@@ -29,7 +30,7 @@ suspend fun TelegramBot.setWebhookInfo(
|
|||||||
certificate: FileId,
|
certificate: FileId,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
) = execute(
|
) = execute(
|
||||||
@@ -46,7 +47,7 @@ suspend fun TelegramBot.setWebhookInfo(
|
|||||||
certificate: MultipartFile,
|
certificate: MultipartFile,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
) = execute(
|
) = execute(
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.doWithRegistration
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.*
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
|
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
|
||||||
|
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.TextSource
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will filter all the messages and include required commands with [commandRegex].
|
||||||
|
*
|
||||||
|
* * In case you wish to get only the commands at the start of message, use [requireCommandAtStart]
|
||||||
|
* * In case you wish to exclude messages with more than one command, you may use [requireSingleCommand]
|
||||||
|
* * In case you wish to exclude messages with commands params, you may use [requireCommandsWithoutParams]
|
||||||
|
*/
|
||||||
|
suspend fun BehaviourContext.waitCommandMessage(
|
||||||
|
commandRegex: Regex,
|
||||||
|
initRequest: Request<*>? = null,
|
||||||
|
errorFactory: NullableRequestBuilder<*> = { null }
|
||||||
|
) = channelFlow {
|
||||||
|
triggersHolder.handleableCommandsHolder.doWithRegistration(
|
||||||
|
commandRegex
|
||||||
|
) {
|
||||||
|
waitTextMessage(initRequest, errorFactory).filter {
|
||||||
|
it.content.textSources.any { it.botCommandTextSourceOrNull() ?.command ?.matches(commandRegex) == true }
|
||||||
|
}.collect {
|
||||||
|
send(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun BehaviourContext.waitCommandMessage(
|
||||||
|
command: String,
|
||||||
|
initRequest: Request<*>? = null,
|
||||||
|
errorFactory: NullableRequestBuilder<*> = { null }
|
||||||
|
) = waitCommandMessage(Regex(command), initRequest, errorFactory)
|
||||||
|
|
||||||
|
fun Flow<CommonMessage<TextContent>>.requireCommandAtStart() = filter {
|
||||||
|
it.content.textSources.firstOrNull() is BotCommandTextSource
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subsequent [Flow] will retrieve only messages with ONE [BotCommandTextSource]. It does not guarantee that this
|
||||||
|
* [BotCommandTextSource] will be at the start of the message
|
||||||
|
*
|
||||||
|
* @see requireCommandAtStart
|
||||||
|
*/
|
||||||
|
fun Flow<CommonMessage<TextContent>>.requireSingleCommand() = filter {
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
it.content.textSources.forEach {
|
||||||
|
if (it is BotCommandTextSource) {
|
||||||
|
count++
|
||||||
|
if (count > 1) {
|
||||||
|
return@filter false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subsequent [Flow] will retrieve only messages without [TextContent.textSources] which are not [BotCommandTextSource]
|
||||||
|
*/
|
||||||
|
fun Flow<CommonMessage<TextContent>>.requireCommandsWithoutParams() = filter {
|
||||||
|
it.content.textSources.none { it !is BotCommandTextSource }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the commands with their arguments and source messages
|
||||||
|
*/
|
||||||
|
fun Flow<CommonMessage<TextContent>>.commandsWithParams(): Flow<Pair<CommonMessage<TextContent>, List<Pair<BotCommandTextSource, Array<TextSource>>>>> = mapNotNull {
|
||||||
|
var currentCommandTextSource: BotCommandTextSource? = null
|
||||||
|
val currentArgs = mutableListOf<TextSource>()
|
||||||
|
val result = mutableListOf<Pair<BotCommandTextSource, Array<TextSource>>>()
|
||||||
|
|
||||||
|
fun addCurrentCommandToResult() {
|
||||||
|
currentCommandTextSource ?.let {
|
||||||
|
result.add(it to currentArgs.toTypedArray())
|
||||||
|
currentArgs.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it.content.textSources.forEach {
|
||||||
|
it.ifBotCommandTextSource {
|
||||||
|
addCurrentCommandToResult()
|
||||||
|
currentCommandTextSource = it
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
currentArgs.add(it)
|
||||||
|
}
|
||||||
|
addCurrentCommandToResult()
|
||||||
|
|
||||||
|
result.toList().takeIf { it.isNotEmpty() } ?.let { result ->
|
||||||
|
it to result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flat [commandsWithParams]. Each [Pair] of [BotCommandTextSource] and its [Array] of arg text sources will
|
||||||
|
* be associated with its source message
|
||||||
|
*/
|
||||||
|
fun Flow<CommonMessage<TextContent>>.flattenCommandsWithParams() = commandsWithParams().flatMapConcat { (message, commandsWithParams) ->
|
||||||
|
commandsWithParams.map {
|
||||||
|
message to it
|
||||||
|
}.asFlow()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use [flattenCommandsWithParams] and filter out the commands which do not [matches] to [commandRegex]
|
||||||
|
*/
|
||||||
|
fun Flow<CommonMessage<TextContent>>.commandParams(commandRegex: Regex) = flattenCommandsWithParams().filter { (_, commandWithParams) ->
|
||||||
|
commandWithParams.first.command.matches(commandRegex)
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.regularTextSourceOrNull
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
|
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
|
||||||
|
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
suspend fun BehaviourContext.waitDeepLinks(
|
||||||
|
initRequest: Request<*>? = null,
|
||||||
|
errorFactory: NullableRequestBuilder<*> = { null },
|
||||||
|
): Flow<Pair<CommonMessage<TextContent>, String>> = waitCommandMessage(
|
||||||
|
"start",
|
||||||
|
initRequest,
|
||||||
|
errorFactory
|
||||||
|
)
|
||||||
|
.requireSingleCommand()
|
||||||
|
.requireCommandAtStart()
|
||||||
|
.flattenCommandsWithParams().mapNotNull {
|
||||||
|
it.first to (it.second.second.singleOrNull() ?.regularTextSourceOrNull() ?.source ?.removePrefix(" ") ?: return@mapNotNull null)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.*
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitDeepLinks
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
|
||||||
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.*
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
|
||||||
|
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||||
|
import dev.inmo.tgbotapi.types.message.content.TextMessage
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource
|
||||||
|
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||||
|
import io.ktor.http.decodeURLQueryComponent
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
|
||||||
|
private val startRegex = Regex("start")
|
||||||
|
suspend fun <BC : BehaviourContext> BC.onDeepLink(
|
||||||
|
initialFilter: SimpleFilter<Pair<TextMessage, String>>? = null,
|
||||||
|
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, Pair<TextMessage, String>, Update> = { (message, _), update -> MessageFilterByChat(this, message, update) },
|
||||||
|
markerFactory: MarkerFactory<Pair<TextMessage, String>, Any> = MarkerFactory { (message, _) -> ByChatMessageMarkerFactory(message) },
|
||||||
|
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, Pair<TextMessage, String>>
|
||||||
|
): Job = on(
|
||||||
|
markerFactory,
|
||||||
|
SimpleFilter<Pair<TextMessage, String>> { (message, _) ->
|
||||||
|
message.content.textSources.size == 2
|
||||||
|
&& message.content.textSources.firstOrNull() ?.asBotCommandTextSource() ?.command == "start"
|
||||||
|
&& message.content.textSources.getOrNull(1) is RegularTextSource
|
||||||
|
} * initialFilter,
|
||||||
|
subcontextUpdatesFilter,
|
||||||
|
scenarioReceiver,
|
||||||
|
) {
|
||||||
|
(it.messageUpdateOrNull()) ?.data ?.commonMessageOrNull() ?.withContentOrNull<TextContent>() ?.let { message ->
|
||||||
|
message to message.content.textSources[1].source.removePrefix(" ").decodeURLQueryComponent()
|
||||||
|
} ?.let(::listOfNotNull)
|
||||||
|
}.also {
|
||||||
|
triggersHolder.handleableCommandsHolder.registerHandleable(startRegex)
|
||||||
|
it.invokeOnCompletion {
|
||||||
|
this@onDeepLink.launchSafelyWithoutExceptions { triggersHolder.handleableCommandsHolder.unregisterHandleable(startRegex) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ fun interface SimpleFilter<in T> {
|
|||||||
suspend operator fun invoke(o: T): Boolean
|
suspend operator fun invoke(o: T): Boolean
|
||||||
}
|
}
|
||||||
val TrueSimpleFilter = SimpleFilter<Any?> { true }
|
val TrueSimpleFilter = SimpleFilter<Any?> { true }
|
||||||
|
val FalseSimpleFilter = SimpleFilter<Any?> { false }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return [SimpleFilter] which will return true in case when all the items in incoming data passed [this] filter
|
* @return [SimpleFilter] which will return true in case when all the items in incoming data passed [this] filter
|
||||||
@@ -28,21 +29,29 @@ fun <T> SimpleFilter<T>.listNone() = SimpleFilter<Iterable<T>> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes an AND (&&) operation between [this] and [other]
|
* Makes an AND (&&) operation between [this] and [other]
|
||||||
|
*
|
||||||
|
* * When both arguments are null, [TrueSimpleFilter] will be returned
|
||||||
*/
|
*/
|
||||||
operator fun <T> SimpleFilter<T>?.times(other: SimpleFilter<T>): SimpleFilter<T> = this ?.let {
|
infix operator fun <T> SimpleFilter<T>?.times(other: SimpleFilter<T>?): SimpleFilter<T> = this ?.let {
|
||||||
SimpleFilter {
|
other ?.let {
|
||||||
this(it) && other(it)
|
SimpleFilter {
|
||||||
}
|
this(it) && other(it)
|
||||||
} ?: other
|
}
|
||||||
|
} ?: it
|
||||||
|
} ?: other ?: TrueSimpleFilter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes an OR (||) operation between [this] and [other]
|
* Makes an OR (||) operation between [this] and [other]
|
||||||
|
*
|
||||||
|
* * When both arguments are null, [TrueSimpleFilter] will be returned
|
||||||
*/
|
*/
|
||||||
operator fun <T> SimpleFilter<T>?.plus(other: SimpleFilter<T>): SimpleFilter<T> = this ?.let {
|
infix operator fun <T> SimpleFilter<T>?.plus(other: SimpleFilter<T>?): SimpleFilter<T> = this ?.let {
|
||||||
SimpleFilter {
|
other ?.let {
|
||||||
this(it) || other(it)
|
SimpleFilter {
|
||||||
}
|
this(it) || other(it)
|
||||||
} ?: other
|
}
|
||||||
|
} ?: it
|
||||||
|
} ?: other ?: TrueSimpleFilter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse results of [this]
|
* Reverse results of [this]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar
|
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ open class HandleableTriggersHolder<T>(
|
|||||||
preset: List<T> = emptyList()
|
preset: List<T> = emptyList()
|
||||||
) {
|
) {
|
||||||
protected val commandsMutex = Mutex()
|
protected val commandsMutex = Mutex()
|
||||||
|
protected val handleableCounts = mutableMapOf<T, Int>()
|
||||||
protected val _handleable = mutableListOf<T>().also {
|
protected val _handleable = mutableListOf<T>().also {
|
||||||
it.addAll(preset)
|
it.addAll(preset)
|
||||||
}
|
}
|
||||||
@@ -16,12 +18,31 @@ open class HandleableTriggersHolder<T>(
|
|||||||
suspend fun registerHandleable(data: T) {
|
suspend fun registerHandleable(data: T) {
|
||||||
commandsMutex.withLock {
|
commandsMutex.withLock {
|
||||||
_handleable.add(data)
|
_handleable.add(data)
|
||||||
|
handleableCounts[data] = (handleableCounts[data] ?: 0) + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun unregisterHandleable(data: T) {
|
suspend fun unregisterHandleable(data: T) {
|
||||||
commandsMutex.withLock {
|
commandsMutex.withLock {
|
||||||
_handleable.remove(data)
|
val newHandleableCount = (handleableCounts[data] ?: 0) - 1
|
||||||
|
if (newHandleableCount > 0) {
|
||||||
|
handleableCounts[data] = newHandleableCount
|
||||||
|
} else {
|
||||||
|
handleableCounts.remove(data)
|
||||||
|
_handleable.remove(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun <T, R> HandleableTriggersHolder<T>.doWithRegistration(
|
||||||
|
data: T,
|
||||||
|
block: suspend () -> R
|
||||||
|
): R {
|
||||||
|
registerHandleable(data)
|
||||||
|
val result = runCatchingSafely {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
unregisterHandleable(data)
|
||||||
|
return result.getOrThrow()
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,13 +35,18 @@ fun newRequestException(
|
|||||||
}
|
}
|
||||||
} ?: CommonRequestException(response, plainAnswer, message, cause)
|
} ?: CommonRequestException(response, plainAnswer, message, cause)
|
||||||
|
|
||||||
|
sealed class BotException(message: String = "Something went wrong", cause: Throwable? = null) : IOException(message, cause)
|
||||||
|
|
||||||
|
class CommonBotException(message: String = "Something went wrong", cause: Throwable? = null) : BotException(message, cause)
|
||||||
|
|
||||||
sealed class RequestException constructor(
|
sealed class RequestException constructor(
|
||||||
val response: Response,
|
val response: Response,
|
||||||
val plainAnswer: String,
|
val plainAnswer: String,
|
||||||
message: String? = null,
|
message: String? = null,
|
||||||
override val cause: Throwable? = null
|
cause: Throwable? = null
|
||||||
) : IOException(
|
) : BotException(
|
||||||
message ?: "Something went wrong"
|
message ?: "Something went wrong",
|
||||||
|
cause
|
||||||
)
|
)
|
||||||
|
|
||||||
class CommonRequestException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
class CommonRequestException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package dev.inmo.tgbotapi.bot.ktor
|
package dev.inmo.tgbotapi.bot.ktor
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||||
import dev.inmo.micro_utils.coroutines.safely
|
import dev.inmo.micro_utils.coroutines.safely
|
||||||
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
||||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
import dev.inmo.tgbotapi.bot.exceptions.*
|
||||||
import dev.inmo.tgbotapi.bot.ktor.base.*
|
import dev.inmo.tgbotapi.bot.ktor.base.*
|
||||||
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
|
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
|
||||||
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
|
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
|
||||||
@@ -48,12 +49,36 @@ class KtorRequestsExecutor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun <T : Any> execute(request: Request<T>): T {
|
override suspend fun <T : Any> execute(request: Request<T>): T {
|
||||||
return runCatching {
|
return runCatchingSafely {
|
||||||
safely(
|
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
|
||||||
{ e ->
|
requestsLimiter.limit {
|
||||||
pipelineStepsHolder.onRequestException(request, e) ?.let { return@safely it }
|
var result: T? = null
|
||||||
|
lateinit var factoryHandledRequest: KtorCallFactory
|
||||||
|
for (potentialFactory in callsFactories) {
|
||||||
|
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
|
||||||
|
result = potentialFactory.makeCall(
|
||||||
|
client,
|
||||||
|
telegramAPIUrlsKeeper,
|
||||||
|
request,
|
||||||
|
jsonFormatter
|
||||||
|
)
|
||||||
|
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
|
||||||
|
if (result != null) {
|
||||||
|
factoryHandledRequest = potentialFactory
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw if (e is ClientRequestException) {
|
result ?.let {
|
||||||
|
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
|
||||||
|
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
val result = it.exceptionOrNull() ?.let { e ->
|
||||||
|
pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it }
|
||||||
|
|
||||||
|
if (e is ClientRequestException) {
|
||||||
|
val exceptionResult = runCatchingSafely {
|
||||||
val content = e.response.bodyAsText()
|
val content = e.response.bodyAsText()
|
||||||
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
||||||
newRequestException(
|
newRequestException(
|
||||||
@@ -61,38 +86,15 @@ class KtorRequestsExecutor(
|
|||||||
content,
|
content,
|
||||||
"Can't get result object from $content"
|
"Can't get result object from $content"
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
e
|
|
||||||
}
|
}
|
||||||
|
exceptionResult.exceptionOrNull() ?.let {
|
||||||
|
CommonBotException(cause = e)
|
||||||
|
} ?: exceptionResult.getOrThrow()
|
||||||
|
} else {
|
||||||
|
CommonBotException(cause = e)
|
||||||
}
|
}
|
||||||
) {
|
} ?.let { Result.failure(it) } ?: it
|
||||||
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
|
pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories)
|
||||||
requestsLimiter.limit {
|
|
||||||
var result: T? = null
|
|
||||||
lateinit var factoryHandledRequest: KtorCallFactory
|
|
||||||
for (potentialFactory in callsFactories) {
|
|
||||||
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
|
|
||||||
result = potentialFactory.makeCall(
|
|
||||||
client,
|
|
||||||
telegramAPIUrlsKeeper,
|
|
||||||
request,
|
|
||||||
jsonFormatter
|
|
||||||
)
|
|
||||||
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
|
|
||||||
if (result != null) {
|
|
||||||
factoryHandledRequest = potentialFactory
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result ?.let {
|
|
||||||
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
|
|
||||||
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.let {
|
|
||||||
pipelineStepsHolder.onRequestReturnResult(it, request, callsFactories)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package dev.inmo.tgbotapi.requests.get
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.files.CustomEmojiSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.StickerSerializer
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
|
|
||||||
|
internal val getCustomEmojiStickersResultSerializer = ListSerializer(StickerSerializer) as DeserializationStrategy<List<CustomEmojiSticker>>
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GetCustomEmojiStickers(
|
||||||
|
@SerialName(customEmojiIdsField)
|
||||||
|
val customEmojiIds: List<CustomEmojiId>
|
||||||
|
): SimpleRequest<List<CustomEmojiSticker>> {
|
||||||
|
override fun method(): String = "getCustomEmojiStickers"
|
||||||
|
override val resultDeserializer: DeserializationStrategy<List<CustomEmojiSticker>>
|
||||||
|
get() = getCustomEmojiStickersResultSerializer
|
||||||
|
override val requestSerializer: SerializationStrategy<*>
|
||||||
|
get() = serializer()
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
package dev.inmo.tgbotapi.requests.get
|
package dev.inmo.tgbotapi.requests.get
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
|
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
|
||||||
|
import dev.inmo.tgbotapi.types.nameField
|
||||||
import dev.inmo.tgbotapi.types.stickerSetNameField
|
import dev.inmo.tgbotapi.types.stickerSetNameField
|
||||||
import dev.inmo.tgbotapi.types.stickers.StickerSet
|
import dev.inmo.tgbotapi.types.stickers.StickerSet
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class GetStickerSet(
|
data class GetStickerSet(
|
||||||
@SerialName(stickerSetNameField)
|
@SerialName(nameField)
|
||||||
val name: String
|
val name: String
|
||||||
): SimpleRequest<StickerSet> {
|
): SimpleRequest<StickerSet> {
|
||||||
override fun method(): String = "getStickerSet"
|
override fun method(): String = "getStickerSet"
|
||||||
|
|||||||
@@ -8,26 +8,8 @@ import dev.inmo.tgbotapi.types.*
|
|||||||
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun CreateNewAnimatedStickerSet(
|
|
||||||
userId: UserId,
|
|
||||||
name: String,
|
|
||||||
title: String,
|
|
||||||
sticker: InputFile,
|
|
||||||
emojis: String,
|
|
||||||
containsMasks: Boolean? = null,
|
|
||||||
maskPosition: MaskPosition? = null
|
|
||||||
): Request<Boolean> {
|
|
||||||
val data = CreateNewAnimatedStickerSet(userId, name, title, emojis, sticker as? FileId, containsMasks, maskPosition)
|
|
||||||
return when (sticker) {
|
|
||||||
is MultipartFile -> CommonMultipartFileRequest(
|
|
||||||
data,
|
|
||||||
mapOf(tgsStickerField to sticker)
|
|
||||||
)
|
|
||||||
is FileId -> data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@Deprecated("Use CreateNewStickerSet class instead")
|
||||||
data class CreateNewAnimatedStickerSet internal constructor(
|
data class CreateNewAnimatedStickerSet internal constructor(
|
||||||
@SerialName(userIdField)
|
@SerialName(userIdField)
|
||||||
override val userId: UserId,
|
override val userId: UserId,
|
||||||
@@ -40,6 +22,7 @@ data class CreateNewAnimatedStickerSet internal constructor(
|
|||||||
@SerialName(tgsStickerField)
|
@SerialName(tgsStickerField)
|
||||||
val sticker: FileId? = null,
|
val sticker: FileId? = null,
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
val containsMasks: Boolean? = null,
|
val containsMasks: Boolean? = null,
|
||||||
@SerialName(maskPositionField)
|
@SerialName(maskPositionField)
|
||||||
override val maskPosition: MaskPosition? = null
|
override val maskPosition: MaskPosition? = null
|
||||||
|
|||||||
@@ -8,36 +8,8 @@ import dev.inmo.tgbotapi.types.*
|
|||||||
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun CreateNewStaticStickerSet(
|
|
||||||
userId: UserId,
|
|
||||||
name: String,
|
|
||||||
title: String,
|
|
||||||
sticker: InputFile,
|
|
||||||
emojis: String,
|
|
||||||
containsMasks: Boolean? = null,
|
|
||||||
maskPosition: MaskPosition? = null
|
|
||||||
): Request<Boolean> {
|
|
||||||
val data = CreateNewStaticStickerSet(userId, name, title, emojis, sticker as? FileId, containsMasks, maskPosition)
|
|
||||||
return when (sticker) {
|
|
||||||
is MultipartFile -> CommonMultipartFileRequest(
|
|
||||||
data,
|
|
||||||
mapOf(pngStickerField to sticker)
|
|
||||||
)
|
|
||||||
is FileId -> data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun CreateNewStickerSet(
|
|
||||||
userId: UserId,
|
|
||||||
name: String,
|
|
||||||
title: String,
|
|
||||||
sticker: InputFile,
|
|
||||||
emojis: String,
|
|
||||||
containsMasks: Boolean? = null,
|
|
||||||
maskPosition: MaskPosition? = null
|
|
||||||
): Request<Boolean> = CreateNewStaticStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@Deprecated("Use CreateNewStickerSet class instead")
|
||||||
data class CreateNewStaticStickerSet internal constructor(
|
data class CreateNewStaticStickerSet internal constructor(
|
||||||
@SerialName(userIdField)
|
@SerialName(userIdField)
|
||||||
override val userId: UserId,
|
override val userId: UserId,
|
||||||
@@ -50,6 +22,7 @@ data class CreateNewStaticStickerSet internal constructor(
|
|||||||
@SerialName(pngStickerField)
|
@SerialName(pngStickerField)
|
||||||
val sticker: FileId? = null,
|
val sticker: FileId? = null,
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
val containsMasks: Boolean? = null,
|
val containsMasks: Boolean? = null,
|
||||||
@SerialName(maskPositionField)
|
@SerialName(maskPositionField)
|
||||||
override val maskPosition: MaskPosition? = null
|
override val maskPosition: MaskPosition? = null
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package dev.inmo.tgbotapi.requests.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.*
|
||||||
|
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
|
||||||
|
import dev.inmo.tgbotapi.requests.stickers.abstracts.CreateStickerSetAction
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
internal fun CreateNewStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
emojis: String,
|
||||||
|
stickerType: StickerType = StickerType.Regular,
|
||||||
|
pngSticker: InputFile? = null,
|
||||||
|
tgsSticker: InputFile? = null,
|
||||||
|
webmSticker: InputFile? = null,
|
||||||
|
maskPosition: MaskPosition? = null
|
||||||
|
): Request<Boolean> {
|
||||||
|
val data = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
stickerType,
|
||||||
|
pngSticker as? FileId,
|
||||||
|
tgsSticker as? FileId,
|
||||||
|
webmSticker as? FileId,
|
||||||
|
maskPosition
|
||||||
|
)
|
||||||
|
return if (pngSticker is MultipartFile || tgsSticker is MultipartFile || webmSticker is MultipartFile) {
|
||||||
|
CommonMultipartFileRequest(
|
||||||
|
data,
|
||||||
|
listOfNotNull(
|
||||||
|
(pngSticker as? MultipartFile) ?.let { pngStickerField to it },
|
||||||
|
(tgsSticker as? MultipartFile) ?.let { tgsStickerField to it },
|
||||||
|
(webmSticker as? MultipartFile) ?.let { webmStickerField to it },
|
||||||
|
).toMap()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CreateNewStickerSet internal constructor(
|
||||||
|
@SerialName(userIdField)
|
||||||
|
override val userId: UserId,
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(emojisField)
|
||||||
|
override val emojis: String,
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
val stickerType: StickerType = StickerType.Regular,
|
||||||
|
@SerialName(pngStickerField)
|
||||||
|
val pngSticker: FileId? = null,
|
||||||
|
@SerialName(tgsStickerField)
|
||||||
|
val tgsSticker: FileId? = null,
|
||||||
|
@SerialName(webmStickerField)
|
||||||
|
val webmSticker: FileId? = null,
|
||||||
|
@SerialName(maskPositionField)
|
||||||
|
override val maskPosition: MaskPosition? = null
|
||||||
|
) : CreateStickerSetAction {
|
||||||
|
init {
|
||||||
|
if(emojis.isEmpty()) {
|
||||||
|
throw IllegalArgumentException("Emojis must not be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val requestSerializer: SerializationStrategy<*>
|
||||||
|
get() = serializer()
|
||||||
|
|
||||||
|
override fun method(): String = "createNewStickerSet"
|
||||||
|
}
|
||||||
@@ -8,26 +8,8 @@ import dev.inmo.tgbotapi.types.*
|
|||||||
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun CreateNewVideoStickerSet(
|
|
||||||
userId: UserId,
|
|
||||||
linkName: String,
|
|
||||||
title: String,
|
|
||||||
sticker: InputFile,
|
|
||||||
emojis: String,
|
|
||||||
containsMasks: Boolean? = null,
|
|
||||||
maskPosition: MaskPosition? = null
|
|
||||||
): Request<Boolean> {
|
|
||||||
val data = CreateNewVideoStickerSet(userId, linkName, title, emojis, sticker as? FileId, containsMasks, maskPosition)
|
|
||||||
return when (sticker) {
|
|
||||||
is MultipartFile -> CommonMultipartFileRequest(
|
|
||||||
data,
|
|
||||||
mapOf(webmStickerField to sticker)
|
|
||||||
)
|
|
||||||
is FileId -> data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@Deprecated("Use CreateNewStickerSet class instead")
|
||||||
data class CreateNewVideoStickerSet internal constructor(
|
data class CreateNewVideoStickerSet internal constructor(
|
||||||
@SerialName(userIdField)
|
@SerialName(userIdField)
|
||||||
override val userId: UserId,
|
override val userId: UserId,
|
||||||
@@ -40,6 +22,7 @@ data class CreateNewVideoStickerSet internal constructor(
|
|||||||
@SerialName(webmStickerField)
|
@SerialName(webmStickerField)
|
||||||
val sticker: FileId? = null,
|
val sticker: FileId? = null,
|
||||||
@SerialName(containsMasksField)
|
@SerialName(containsMasksField)
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
val containsMasks: Boolean? = null,
|
val containsMasks: Boolean? = null,
|
||||||
@SerialName(maskPositionField)
|
@SerialName(maskPositionField)
|
||||||
override val maskPosition: MaskPosition? = null
|
override val maskPosition: MaskPosition? = null
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package dev.inmo.tgbotapi.requests.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.InputFile
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
|
import dev.inmo.tgbotapi.types.StickerType
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
|
||||||
|
fun CreateNewRegularStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
StickerType.Regular,
|
||||||
|
pngSticker = sticker
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewRegularVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
StickerType.Regular,
|
||||||
|
webmSticker = sticker
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewRegularAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
StickerType.Regular,
|
||||||
|
tgsSticker = sticker
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun CreateNewMaskStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
StickerType.Mask,
|
||||||
|
pngSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewMaskVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
StickerType.Mask,
|
||||||
|
webmSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewMaskAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
maskPosition: MaskPosition
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
StickerType.Mask,
|
||||||
|
tgsSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package dev.inmo.tgbotapi.requests.stickers
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.InputFile
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
|
import dev.inmo.tgbotapi.types.StickerType
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
|
|
||||||
|
fun CreateNewVideoStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
linkName: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
containsMasks: Boolean? = null,
|
||||||
|
maskPosition: MaskPosition? = null
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
linkName,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
|
||||||
|
webmSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewStaticStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
containsMasks: Boolean? = null,
|
||||||
|
maskPosition: MaskPosition? = null
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
|
||||||
|
pngSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
containsMasks: Boolean? = null,
|
||||||
|
maskPosition: MaskPosition? = null
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
|
||||||
|
pngSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
fun CreateNewAnimatedStickerSet(
|
||||||
|
userId: UserId,
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
sticker: InputFile,
|
||||||
|
emojis: String,
|
||||||
|
containsMasks: Boolean? = null,
|
||||||
|
maskPosition: MaskPosition? = null
|
||||||
|
): Request<Boolean> = CreateNewStickerSet(
|
||||||
|
userId,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
emojis,
|
||||||
|
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
|
||||||
|
tgsSticker = sticker,
|
||||||
|
maskPosition = maskPosition
|
||||||
|
)
|
||||||
@@ -19,7 +19,7 @@ class MultipartSetWebhookRequest(
|
|||||||
certificate: MultipartFile,
|
certificate: MultipartFile,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
) : SetWebhookRequest(), MultipartRequest<Boolean> by MultipartRequestImpl(
|
) : SetWebhookRequest(), MultipartRequest<Boolean> by MultipartRequestImpl(
|
||||||
@@ -40,7 +40,7 @@ fun SetWebhook(
|
|||||||
certificate: MultipartFile,
|
certificate: MultipartFile,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
): MultipartSetWebhookRequest = MultipartSetWebhookRequest(
|
): MultipartSetWebhookRequest = MultipartSetWebhookRequest(
|
||||||
@@ -58,7 +58,7 @@ fun SetWebhook(
|
|||||||
certificate: FileId,
|
certificate: FileId,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
): SetWebhook = SetWebhook(
|
): SetWebhook = SetWebhook(
|
||||||
@@ -84,7 +84,7 @@ fun SetWebhook(
|
|||||||
certificate: InputFile,
|
certificate: InputFile,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
) = when (certificate) {
|
) = when (certificate) {
|
||||||
@@ -104,7 +104,7 @@ fun SetWebhook(
|
|||||||
url: String,
|
url: String,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
dropPendingUpdates: Boolean? = null,
|
dropPendingUpdates: Boolean? = null,
|
||||||
secretToken: String? = null
|
secretToken: String? = null
|
||||||
) = SetWebhook(
|
) = SetWebhook(
|
||||||
@@ -135,7 +135,7 @@ data class SetWebhook internal constructor(
|
|||||||
@SerialName(maxAllowedConnectionsField)
|
@SerialName(maxAllowedConnectionsField)
|
||||||
val maxAllowedConnections: Int? = null,
|
val maxAllowedConnections: Int? = null,
|
||||||
@SerialName(allowedUpdatesField)
|
@SerialName(allowedUpdatesField)
|
||||||
val allowedUpdates: List<String>? = null,
|
val allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
@SerialName(dropPendingUpdatesField)
|
@SerialName(dropPendingUpdatesField)
|
||||||
val dropPendingUpdates: Boolean? = null,
|
val dropPendingUpdates: Boolean? = null,
|
||||||
@SerialName(secretTokenField)
|
@SerialName(secretTokenField)
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
package dev.inmo.tgbotapi.types
|
package dev.inmo.tgbotapi.types
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.utils.BuiltinMimeTypes
|
import dev.inmo.tgbotapi.utils.BuiltinMimeTypes
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlin.jvm.JvmInline
|
||||||
|
|
||||||
typealias Identifier = Long
|
typealias Identifier = Long
|
||||||
typealias MessageIdentifier = Long
|
typealias MessageIdentifier = Long
|
||||||
@@ -28,6 +35,11 @@ typealias GooglePlaceId = String
|
|||||||
typealias GooglePlaceType = String
|
typealias GooglePlaceType = String
|
||||||
typealias MembersLimit = Int
|
typealias MembersLimit = Int
|
||||||
typealias WebAppQueryId = String
|
typealias WebAppQueryId = String
|
||||||
|
@Serializable
|
||||||
|
@JvmInline
|
||||||
|
value class CustomEmojiId(
|
||||||
|
val string: String
|
||||||
|
)
|
||||||
|
|
||||||
typealias Seconds = Int
|
typealias Seconds = Int
|
||||||
typealias MilliSeconds = Long
|
typealias MilliSeconds = Long
|
||||||
@@ -37,6 +49,40 @@ typealias UnixTimeStamp = LongSeconds
|
|||||||
typealias Meters = Float
|
typealias Meters = Float
|
||||||
typealias Degrees = Int
|
typealias Degrees = Int
|
||||||
|
|
||||||
|
@Serializable(StickerType.Serializer::class)
|
||||||
|
sealed interface StickerType {
|
||||||
|
val type: String
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
object Regular : StickerType { override val type: String = "regular" }
|
||||||
|
@Serializable
|
||||||
|
object Mask : StickerType { override val type: String = "mask" }
|
||||||
|
@Serializable
|
||||||
|
object CustomEmoji : StickerType { override val type: String = "custom_emoji" }
|
||||||
|
@Serializable
|
||||||
|
data class Unknown(override val type: String = "custom_emoji") : StickerType
|
||||||
|
|
||||||
|
object Serializer : KSerializer<StickerType> {
|
||||||
|
override val descriptor: SerialDescriptor = String.serializer().descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): StickerType {
|
||||||
|
return when (val type = decoder.decodeString()) {
|
||||||
|
Regular.type -> Regular
|
||||||
|
Mask.type -> Mask
|
||||||
|
CustomEmoji.type -> CustomEmoji
|
||||||
|
else -> Unknown(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: StickerType) {
|
||||||
|
encoder.encodeString(value.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val usernameRegex = Regex("@[\\w\\d_]+")
|
||||||
|
|
||||||
val degreesLimit = 1 .. 360
|
val degreesLimit = 1 .. 360
|
||||||
val horizontalAccuracyLimit = 0F .. 1500F
|
val horizontalAccuracyLimit = 0F .. 1500F
|
||||||
|
|
||||||
@@ -120,12 +166,15 @@ const val languageCodeField = "language_code"
|
|||||||
const val addedToAttachmentMenuField = "added_to_attachment_menu"
|
const val addedToAttachmentMenuField = "added_to_attachment_menu"
|
||||||
const val isPremiumField = "is_premium"
|
const val isPremiumField = "is_premium"
|
||||||
const val hasPrivateForwardsField = "has_private_forwards"
|
const val hasPrivateForwardsField = "has_private_forwards"
|
||||||
|
const val hasRestrictedVoiceAndVideoMessagesField = "has_restricted_voice_and_video_messages"
|
||||||
const val canJoinGroupsField = "can_join_groups"
|
const val canJoinGroupsField = "can_join_groups"
|
||||||
const val canReadAllGroupMessagesField = "can_read_all_group_messages"
|
const val canReadAllGroupMessagesField = "can_read_all_group_messages"
|
||||||
const val supportInlineQueriesField = "supports_inline_queries"
|
const val supportInlineQueriesField = "supports_inline_queries"
|
||||||
const val textEntitiesField = "text_entities"
|
const val textEntitiesField = "text_entities"
|
||||||
const val entitiesField = "entities"
|
const val entitiesField = "entities"
|
||||||
const val stickerSetNameField = "set_name"
|
const val stickerSetNameField = "set_name"
|
||||||
|
const val customEmojiIdField = "custom_emoji_id"
|
||||||
|
const val customEmojiIdsField = "custom_emoji_ids"
|
||||||
const val premiumAnimationField = "premium_animation"
|
const val premiumAnimationField = "premium_animation"
|
||||||
const val stickerSetNameFullField = "sticker_set_name"
|
const val stickerSetNameFullField = "sticker_set_name"
|
||||||
const val slowModeDelayField = "slow_mode_delay"
|
const val slowModeDelayField = "slow_mode_delay"
|
||||||
@@ -290,6 +339,7 @@ const val tgsStickerField = "tgs_sticker"
|
|||||||
const val webmStickerField = "webm_sticker"
|
const val webmStickerField = "webm_sticker"
|
||||||
const val oldChatMemberField = "old_chat_member"
|
const val oldChatMemberField = "old_chat_member"
|
||||||
const val newChatMemberField = "new_chat_member"
|
const val newChatMemberField = "new_chat_member"
|
||||||
|
const val stickerTypeField = "sticker_type"
|
||||||
|
|
||||||
const val okField = "ok"
|
const val okField = "ok"
|
||||||
const val captionField = "caption"
|
const val captionField = "caption"
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ data class ExtendedPrivateChatImpl(
|
|||||||
@SerialName(bioField)
|
@SerialName(bioField)
|
||||||
override val bio: String = "",
|
override val bio: String = "",
|
||||||
@SerialName(hasPrivateForwardsField)
|
@SerialName(hasPrivateForwardsField)
|
||||||
override val hasPrivateForwards: Boolean = false
|
override val hasPrivateForwards: Boolean = false,
|
||||||
|
@SerialName(hasRestrictedVoiceAndVideoMessagesField)
|
||||||
|
override val hasRestrictedVoiceAndVideoMessages: Boolean = false
|
||||||
) : ExtendedPrivateChat
|
) : ExtendedPrivateChat
|
||||||
|
|
||||||
typealias ExtendedUser = ExtendedPrivateChatImpl
|
typealias ExtendedUser = ExtendedPrivateChatImpl
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ sealed interface ExtendedGroupChat : GroupChat, ExtendedPublicChat {
|
|||||||
sealed interface ExtendedPrivateChat : PrivateChat, ExtendedChat {
|
sealed interface ExtendedPrivateChat : PrivateChat, ExtendedChat {
|
||||||
val bio: String
|
val bio: String
|
||||||
val hasPrivateForwards: Boolean
|
val hasPrivateForwards: Boolean
|
||||||
|
val hasRestrictedVoiceAndVideoMessages: Boolean
|
||||||
|
|
||||||
val allowCreateUserIdLink: Boolean
|
val allowCreateUserIdLink: Boolean
|
||||||
get() = hasPrivateForwards
|
get() = hasPrivateForwards
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ import dev.inmo.tgbotapi.requests.abstracts.FileId
|
|||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
|
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@RiskFeature("This class is used for serialization/deserialization of Sticker interface")
|
@RiskFeature("This class is used for serialization/deserialization of Sticker interface")
|
||||||
data class StickerSurrogate(
|
data class StickerSurrogate(
|
||||||
val file_id: FileId,
|
val file_id: FileId,
|
||||||
val file_unique_id: FileUniqueId,
|
val file_unique_id: FileUniqueId,
|
||||||
|
val type: StickerType,
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val height: Int,
|
val height: Int,
|
||||||
val is_animated: Boolean? = null,
|
val is_animated: Boolean? = null,
|
||||||
@@ -21,33 +24,138 @@ data class StickerSurrogate(
|
|||||||
val thumb: PhotoSize? = null,
|
val thumb: PhotoSize? = null,
|
||||||
val emoji: String? = null,
|
val emoji: String? = null,
|
||||||
val set_name: StickerSetName? = null,
|
val set_name: StickerSetName? = null,
|
||||||
|
val premium_animation: File? = null,
|
||||||
val mask_position: MaskPosition? = null,
|
val mask_position: MaskPosition? = null,
|
||||||
val file_size: Long? = null,
|
val custom_emoji_id: CustomEmojiId? = null,
|
||||||
val premium_animation: File? = null
|
val file_size: Long? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO:: Serializer
|
// TODO:: Serializer
|
||||||
@Serializable(StickerSerializer::class)
|
@Serializable(StickerSerializer::class)
|
||||||
sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile {
|
sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile {
|
||||||
val emoji: String?
|
val emoji: String?
|
||||||
val maskPosition: MaskPosition?
|
|
||||||
val stickerSetName: StickerSetName?
|
val stickerSetName: StickerSetName?
|
||||||
val premiumAnimationFile: File?
|
|
||||||
|
|
||||||
val isAnimated
|
val isAnimated
|
||||||
get() = this is AnimatedSticker
|
get() = false
|
||||||
val isVideo
|
val isVideo
|
||||||
get() = this is VideoSticker
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
object StickerSerializer : KSerializer<Sticker> {
|
object StickerSerializer : KSerializer<Sticker> {
|
||||||
override val descriptor: SerialDescriptor = StickerSurrogate.serializer().descriptor
|
override val descriptor: SerialDescriptor = StickerSurrogate.serializer().descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Sticker {
|
override fun deserialize(decoder: Decoder): Sticker {
|
||||||
val surrogate = StickerSurrogate.serializer().deserialize(decoder)
|
val json = JsonElement.serializer().deserialize(decoder)
|
||||||
|
val surrogate = nonstrictJsonFormat.decodeFromJsonElement(StickerSurrogate.serializer(), json)
|
||||||
|
|
||||||
return when {
|
return when (surrogate.type) {
|
||||||
surrogate.is_animated == true -> AnimatedSticker(
|
StickerType.Regular -> when {
|
||||||
|
surrogate.is_animated == true -> RegularAnimatedSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.premium_animation,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
surrogate.is_video == true -> RegularVideoSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.premium_animation,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
else -> RegularSimpleSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.premium_animation,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
StickerType.Mask -> when {
|
||||||
|
surrogate.is_animated == true -> MaskAnimatedSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.mask_position ?: error("For mask stickers field mask_position should be presented"),
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
surrogate.is_video == true -> MaskVideoSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.mask_position ?: error("For mask stickers field mask_position should be presented"),
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
else -> MaskSimpleSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.mask_position ?: error("For mask stickers field mask_position should be presented"),
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
StickerType.CustomEmoji -> when {
|
||||||
|
surrogate.is_animated == true -> CustomEmojiAnimatedSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.custom_emoji_id ?: error("For mask stickers field mask_position should be presented"),
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
surrogate.is_video == true -> CustomEmojiVideoSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.custom_emoji_id ?: error("For mask stickers field mask_position should be presented"),
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
else -> CustomEmojiSimpleSticker(
|
||||||
|
surrogate.file_id,
|
||||||
|
surrogate.file_unique_id,
|
||||||
|
surrogate.width,
|
||||||
|
surrogate.height,
|
||||||
|
surrogate.custom_emoji_id ?: error("For mask stickers field mask_position should be presented"),
|
||||||
|
surrogate.thumb,
|
||||||
|
surrogate.emoji,
|
||||||
|
surrogate.set_name,
|
||||||
|
surrogate.file_size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is StickerType.Unknown -> UnknownSticker(
|
||||||
surrogate.file_id,
|
surrogate.file_id,
|
||||||
surrogate.file_unique_id,
|
surrogate.file_unique_id,
|
||||||
surrogate.width,
|
surrogate.width,
|
||||||
@@ -55,33 +163,8 @@ object StickerSerializer : KSerializer<Sticker> {
|
|||||||
surrogate.thumb,
|
surrogate.thumb,
|
||||||
surrogate.emoji,
|
surrogate.emoji,
|
||||||
surrogate.set_name,
|
surrogate.set_name,
|
||||||
surrogate.premium_animation,
|
surrogate.file_size,
|
||||||
surrogate.mask_position,
|
json
|
||||||
surrogate.file_size
|
|
||||||
)
|
|
||||||
surrogate.is_video == true -> VideoSticker(
|
|
||||||
surrogate.file_id,
|
|
||||||
surrogate.file_unique_id,
|
|
||||||
surrogate.width,
|
|
||||||
surrogate.height,
|
|
||||||
surrogate.thumb,
|
|
||||||
surrogate.emoji,
|
|
||||||
surrogate.set_name,
|
|
||||||
surrogate.premium_animation,
|
|
||||||
surrogate.mask_position,
|
|
||||||
surrogate.file_size
|
|
||||||
)
|
|
||||||
else -> SimpleSticker(
|
|
||||||
surrogate.file_id,
|
|
||||||
surrogate.file_unique_id,
|
|
||||||
surrogate.width,
|
|
||||||
surrogate.height,
|
|
||||||
surrogate.thumb,
|
|
||||||
surrogate.emoji,
|
|
||||||
surrogate.set_name,
|
|
||||||
surrogate.premium_animation,
|
|
||||||
surrogate.mask_position,
|
|
||||||
surrogate.file_size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,53 +176,23 @@ object StickerSerializer : KSerializer<Sticker> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SimpleSticker(
|
sealed interface VideoSticker : Sticker {
|
||||||
@SerialName(fileIdField)
|
override val isVideo: Boolean
|
||||||
override val fileId: FileId,
|
get() = true
|
||||||
@SerialName(fileUniqueIdField)
|
}
|
||||||
override val fileUniqueId: FileUniqueId,
|
|
||||||
@SerialName(widthField)
|
|
||||||
override val width: Int,
|
|
||||||
@SerialName(heightField)
|
|
||||||
override val height: Int,
|
|
||||||
@SerialName(thumbField)
|
|
||||||
override val thumb: PhotoSize? = null,
|
|
||||||
@SerialName(emojiField)
|
|
||||||
override val emoji: String? = null,
|
|
||||||
@SerialName(stickerSetNameField)
|
|
||||||
override val stickerSetName: StickerSetName? = null,
|
|
||||||
@SerialName(premiumAnimationField)
|
|
||||||
override val premiumAnimationFile: File?,
|
|
||||||
@SerialName(maskPositionField)
|
|
||||||
override val maskPosition: MaskPosition? = null,
|
|
||||||
@SerialName(fileSizeField)
|
|
||||||
override val fileSize: Long? = null,
|
|
||||||
) : Sticker
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AnimatedSticker(
|
sealed interface AnimatedSticker : Sticker {
|
||||||
@SerialName(fileIdField)
|
override val isAnimated: Boolean
|
||||||
override val fileId: FileId,
|
get() = true
|
||||||
@SerialName(fileUniqueIdField)
|
}
|
||||||
override val fileUniqueId: FileUniqueId,
|
|
||||||
@SerialName(widthField)
|
|
||||||
override val width: Int,
|
|
||||||
@SerialName(heightField)
|
|
||||||
override val height: Int,
|
|
||||||
@SerialName(thumbField)
|
|
||||||
override val thumb: PhotoSize? = null,
|
|
||||||
@SerialName(emojiField)
|
|
||||||
override val emoji: String? = null,
|
|
||||||
@SerialName(stickerSetNameField)
|
|
||||||
override val stickerSetName: StickerSetName? = null,
|
|
||||||
@SerialName(premiumAnimationField)
|
|
||||||
override val premiumAnimationFile: File?,
|
|
||||||
@SerialName(maskPositionField)
|
|
||||||
override val maskPosition: MaskPosition? = null,
|
|
||||||
@SerialName(fileSizeField)
|
|
||||||
override val fileSize: Long? = null,
|
|
||||||
) : Sticker
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class VideoSticker(
|
sealed interface RegularSticker : Sticker {
|
||||||
|
val premiumAnimationFile: File?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RegularSimpleSticker(
|
||||||
@SerialName(fileIdField)
|
@SerialName(fileIdField)
|
||||||
override val fileId: FileId,
|
override val fileId: FileId,
|
||||||
@SerialName(fileUniqueIdField)
|
@SerialName(fileUniqueIdField)
|
||||||
@@ -156,8 +209,209 @@ data class VideoSticker(
|
|||||||
override val stickerSetName: StickerSetName? = null,
|
override val stickerSetName: StickerSetName? = null,
|
||||||
@SerialName(premiumAnimationField)
|
@SerialName(premiumAnimationField)
|
||||||
override val premiumAnimationFile: File?,
|
override val premiumAnimationFile: File?,
|
||||||
@SerialName(maskPositionField)
|
|
||||||
override val maskPosition: MaskPosition? = null,
|
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null,
|
override val fileSize: Long? = null,
|
||||||
|
) : RegularSticker
|
||||||
|
@Deprecated("Renamed", ReplaceWith("SimpleRegularSticker", "dev.inmo.tgbotapi.types.files.SimpleRegularSticker"))
|
||||||
|
typealias SimpleSticker = RegularSimpleSticker
|
||||||
|
@Serializable
|
||||||
|
data class RegularAnimatedSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(premiumAnimationField)
|
||||||
|
override val premiumAnimationFile: File?,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : RegularSticker, AnimatedSticker
|
||||||
|
@Serializable
|
||||||
|
data class RegularVideoSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(premiumAnimationField)
|
||||||
|
override val premiumAnimationFile: File?,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : RegularSticker, VideoSticker
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed interface MaskSticker : Sticker {
|
||||||
|
val maskPosition: MaskPosition
|
||||||
|
}
|
||||||
|
@Serializable
|
||||||
|
data class MaskSimpleSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(maskPositionField)
|
||||||
|
override val maskPosition: MaskPosition,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : MaskSticker
|
||||||
|
@Serializable
|
||||||
|
data class MaskAnimatedSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(maskPositionField)
|
||||||
|
override val maskPosition: MaskPosition,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : MaskSticker, AnimatedSticker
|
||||||
|
@Serializable
|
||||||
|
data class MaskVideoSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(maskPositionField)
|
||||||
|
override val maskPosition: MaskPosition,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : MaskSticker, VideoSticker
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed interface CustomEmojiSticker : Sticker {
|
||||||
|
val customEmojiId: CustomEmojiId
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiSimpleSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(customEmojiIdField)
|
||||||
|
override val customEmojiId: CustomEmojiId,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : CustomEmojiSticker
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiAnimatedSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(customEmojiIdField)
|
||||||
|
override val customEmojiId: CustomEmojiId,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : CustomEmojiSticker, AnimatedSticker
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiVideoSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(customEmojiIdField)
|
||||||
|
override val customEmojiId: CustomEmojiId,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
) : CustomEmojiSticker, VideoSticker
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class UnknownSticker(
|
||||||
|
@SerialName(fileIdField)
|
||||||
|
override val fileId: FileId,
|
||||||
|
@SerialName(fileUniqueIdField)
|
||||||
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(widthField)
|
||||||
|
override val width: Int,
|
||||||
|
@SerialName(heightField)
|
||||||
|
override val height: Int,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
@SerialName(emojiField)
|
||||||
|
override val emoji: String? = null,
|
||||||
|
@SerialName(stickerSetNameField)
|
||||||
|
override val stickerSetName: StickerSetName? = null,
|
||||||
|
@SerialName(fileSizeField)
|
||||||
|
override val fileSize: Long? = null,
|
||||||
|
val raw: JsonElement
|
||||||
) : Sticker
|
) : Sticker
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.types.message
|
package dev.inmo.tgbotapi.types.message
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.*
|
import dev.inmo.tgbotapi.types.message.textsources.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -11,7 +12,8 @@ internal data class RawMessageEntity(
|
|||||||
val length: Int,
|
val length: Int,
|
||||||
val url: String? = null,
|
val url: String? = null,
|
||||||
val user: User? = null,
|
val user: User? = null,
|
||||||
val language: String? = null
|
val language: String? = null,
|
||||||
|
val custom_emoji_id: CustomEmojiId? = null
|
||||||
) {
|
) {
|
||||||
internal val range by lazy {
|
internal val range by lazy {
|
||||||
offset until (offset + length)
|
offset until (offset + length)
|
||||||
@@ -50,6 +52,7 @@ internal fun RawMessageEntity.asTextSource(
|
|||||||
"underline" -> UnderlineTextSource(sourceSubstring, subPartsWithRegulars)
|
"underline" -> UnderlineTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"strikethrough" -> StrikethroughTextSource(sourceSubstring, subPartsWithRegulars)
|
"strikethrough" -> StrikethroughTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"spoiler" -> SpoilerTextSource(sourceSubstring, subPartsWithRegulars)
|
"spoiler" -> SpoilerTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
|
"custom_emoji" -> CustomEmojiTextSource(sourceSubstring, custom_emoji_id ?: error("For custom emoji custom_emoji_id should exists"), subPartsWithRegulars)
|
||||||
else -> RegularTextSource(sourceSubstring)
|
else -> RegularTextSource(sourceSubstring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +161,8 @@ internal fun TextSource.toRawMessageEntities(offset: Int = 0): List<RawMessageEn
|
|||||||
is UnderlineTextSource -> RawMessageEntity("underline", offset, length)
|
is UnderlineTextSource -> RawMessageEntity("underline", offset, length)
|
||||||
is StrikethroughTextSource -> RawMessageEntity("strikethrough", offset, length)
|
is StrikethroughTextSource -> RawMessageEntity("strikethrough", offset, length)
|
||||||
is SpoilerTextSource -> RawMessageEntity("spoiler", offset, length)
|
is SpoilerTextSource -> RawMessageEntity("spoiler", offset, length)
|
||||||
else -> null
|
is CustomEmojiTextSource -> RawMessageEntity("custom_emoji", offset, length, custom_emoji_id = customEmojiId)
|
||||||
|
is RegularTextSource -> null
|
||||||
}
|
}
|
||||||
) + if (this is MultilevelTextSource) {
|
) + if (this is MultilevelTextSource) {
|
||||||
subsources.toRawMessageEntities(offset)
|
subsources.toRawMessageEntities(offset)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.types.message.textsources
|
package dev.inmo.tgbotapi.types.message.textsources
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.usernameRegex
|
||||||
|
import dev.inmo.tgbotapi.types.Username
|
||||||
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.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -16,6 +18,9 @@ data class BotCommandTextSource @RiskFeature(DirectInvocationOfTextSourceConstru
|
|||||||
val command: String by lazy {
|
val command: String by lazy {
|
||||||
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
|
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
|
||||||
}
|
}
|
||||||
|
val username: Username? by lazy {
|
||||||
|
Username(usernameRegex.find(source) ?.value ?: return@lazy null)
|
||||||
|
}
|
||||||
|
|
||||||
override val markdown: String by lazy { source.commandMarkdown() }
|
override val markdown: String by lazy { source.commandMarkdown() }
|
||||||
override val markdownV2: String by lazy { source.commandMarkdownV2() }
|
override val markdownV2: String by lazy { source.commandMarkdownV2() }
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package dev.inmo.tgbotapi.types.message.textsources
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
|
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||||
|
import dev.inmo.tgbotapi.utils.internal.*
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see customEmoji
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
|
override val source: String,
|
||||||
|
val customEmojiId: CustomEmojiId,
|
||||||
|
override val subsources: TextSourcesList
|
||||||
|
) : MultilevelTextSource {
|
||||||
|
override val markdown: String by lazy { source.customEmojiMarkdown() }
|
||||||
|
override val markdownV2: String by lazy { source.customEmojiMarkdownV2() }
|
||||||
|
override val html: String by lazy { source.customEmojiHTML() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_API_USAGE")
|
||||||
|
inline fun customEmoji(emojiId: CustomEmojiId, parts: TextSourcesList) = CustomEmojiTextSource(parts.makeString(), emojiId, parts)
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun customEmoji(emojiId: CustomEmojiId, vararg parts: TextSource) = customEmoji(emojiId, parts.toList())
|
||||||
|
/**
|
||||||
|
* Without sharp (#)
|
||||||
|
*/
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun customEmoji(emojiId: CustomEmojiId, text: String) = customEmoji(emojiId, regular(text))
|
||||||
@@ -36,7 +36,7 @@ sealed interface MultilevelTextSource : TextSource {
|
|||||||
val subsources: List<TextSource>
|
val subsources: List<TextSource>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> {
|
fun List<TextSource>.splitForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
@@ -70,13 +70,27 @@ fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = n
|
|||||||
* This method will prepare [TextSource]s list for messages. Remember, that first part will be separated with
|
* This method will prepare [TextSource]s list for messages. Remember, that first part will be separated with
|
||||||
* [captionLength] and all others with
|
* [captionLength] and all others with
|
||||||
*/
|
*/
|
||||||
fun List<TextSource>.separateForCaption(): List<List<TextSource>> {
|
fun List<TextSource>.splitForCaption(): List<List<TextSource>> {
|
||||||
val captionPart = separateForMessage(captionLength, 1).first()
|
val captionPart = splitForMessage(captionLength, 1).first()
|
||||||
return listOf(captionPart) + minus(captionPart).separateForMessage(textLength)
|
return listOf(captionPart) + minus(captionPart).splitForMessage(textLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will prepare [TextSource]s list for messages with [textLength]
|
* This method will prepare [TextSource]s list for messages with [textLength]
|
||||||
*/
|
*/
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun List<TextSource>.separateForText(): List<List<TextSource>> = separateForMessage(textLength)
|
inline fun List<TextSource>.splitForText(): List<List<TextSource>> = splitForMessage(textLength)
|
||||||
|
|
||||||
|
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> = splitForMessage(limit, numberOfParts)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will prepare [TextSource]s list for messages. Remember, that first part will be separated with
|
||||||
|
* [captionLength] and all others with
|
||||||
|
*/
|
||||||
|
fun List<TextSource>.separateForCaption(): List<List<TextSource>> = splitForCaption()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will prepare [TextSource]s list for messages with [textLength]
|
||||||
|
*/
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun List<TextSource>.separateForText(): List<List<TextSource>> = splitForText()
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ private val baseSerializers: Map<String, KSerializer<out TextSource>> = mapOf(
|
|||||||
"hashtag" to HashTagTextSource.serializer(),
|
"hashtag" to HashTagTextSource.serializer(),
|
||||||
"cashtag" to CashTagTextSource.serializer(),
|
"cashtag" to CashTagTextSource.serializer(),
|
||||||
"spoiler" to SpoilerTextSource.serializer(),
|
"spoiler" to SpoilerTextSource.serializer(),
|
||||||
|
"custom_emoji" to CustomEmojiTextSource.serializer(),
|
||||||
)
|
)
|
||||||
|
|
||||||
object TextSourceSerializer : TypedSerializer<TextSource>(TextSource::class, baseSerializers) {
|
object TextSourceSerializer : TypedSerializer<TextSource>(TextSource::class, baseSerializers) {
|
||||||
|
|||||||
@@ -1,25 +1,298 @@
|
|||||||
package dev.inmo.tgbotapi.types.stickers
|
package dev.inmo.tgbotapi.types.stickers
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.files.PhotoSize
|
import dev.inmo.tgbotapi.types.files.*
|
||||||
import dev.inmo.tgbotapi.types.files.Sticker
|
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class StickerSet(
|
data class SurrogateStickerSet(
|
||||||
@SerialName(nameField)
|
|
||||||
val name: String,
|
val name: String,
|
||||||
@SerialName(titleField)
|
|
||||||
val title: String,
|
val title: String,
|
||||||
@SerialName(stickersField)
|
val sticker_type: StickerType,
|
||||||
val stickers: List<Sticker>,
|
val is_animated: Boolean? = false,
|
||||||
@SerialName(isAnimatedField)
|
val is_video: Boolean? = false,
|
||||||
val isAnimated: Boolean = false,
|
val stickers: List<@Serializable(StickerSerializer::class) Sticker> = emptyList(),
|
||||||
@SerialName(isVideoField)
|
|
||||||
val isVideo: Boolean = false,
|
|
||||||
@SerialName(containsMasksField)
|
|
||||||
val containsMasks: Boolean = false,
|
|
||||||
@SerialName(thumbField)
|
|
||||||
val thumb: PhotoSize? = null
|
val thumb: PhotoSize? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable(StickerSet.Serializer::class)
|
||||||
|
sealed interface StickerSet {
|
||||||
|
val name: String
|
||||||
|
val title: String
|
||||||
|
val stickerType: StickerType
|
||||||
|
val stickers: List<Sticker>
|
||||||
|
val isAnimated: Boolean
|
||||||
|
get() = false
|
||||||
|
val isVideo: Boolean
|
||||||
|
get() = false
|
||||||
|
val thumb: PhotoSize?
|
||||||
|
@Deprecated("Will be removed soon due to its redundancy")
|
||||||
|
val containsMasks: Boolean
|
||||||
|
get() = this is MaskStickerSet
|
||||||
|
|
||||||
|
object Serializer : KSerializer<StickerSet> {
|
||||||
|
override val descriptor: SerialDescriptor = JsonElement.serializer().descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): StickerSet {
|
||||||
|
val json = JsonElement.serializer().deserialize(decoder)
|
||||||
|
val surrogate = nonstrictJsonFormat.decodeFromJsonElement(SurrogateStickerSet.serializer(), json)
|
||||||
|
|
||||||
|
return when (surrogate.sticker_type) {
|
||||||
|
StickerType.CustomEmoji -> when {
|
||||||
|
surrogate.is_animated == true -> CustomEmojiAnimatedStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<CustomEmojiAnimatedSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
surrogate.is_video == true -> CustomEmojiVideoStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<CustomEmojiVideoSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
else -> CustomEmojiSimpleStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<CustomEmojiSimpleSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
}
|
||||||
|
StickerType.Mask -> when {
|
||||||
|
surrogate.is_animated == true -> MaskAnimatedStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<MaskAnimatedSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
surrogate.is_video == true -> MaskVideoStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<MaskVideoSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
else -> MaskSimpleStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<MaskSimpleSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
}
|
||||||
|
StickerType.Regular -> when {
|
||||||
|
surrogate.is_animated == true -> RegularAnimatedStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<RegularAnimatedSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
surrogate.is_video == true -> RegularVideoStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<RegularVideoSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
else -> RegularSimpleStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<RegularSimpleSticker>(),
|
||||||
|
surrogate.thumb
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is StickerType.Unknown -> UnknownStickerSet(
|
||||||
|
surrogate.name,
|
||||||
|
surrogate.title,
|
||||||
|
surrogate.stickers.filterIsInstance<RegularSimpleSticker>(),
|
||||||
|
surrogate.sticker_type,
|
||||||
|
surrogate.thumb,
|
||||||
|
json
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: StickerSet) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed interface AnimatedStickerSet : StickerSet {
|
||||||
|
override val isAnimated: Boolean
|
||||||
|
get() = true
|
||||||
|
}
|
||||||
|
@Serializable
|
||||||
|
sealed interface VideoStickerSet : StickerSet {
|
||||||
|
override val isVideo: Boolean
|
||||||
|
get() = true
|
||||||
|
}
|
||||||
|
@Serializable
|
||||||
|
sealed interface RegularStickerSet : StickerSet
|
||||||
|
@Serializable
|
||||||
|
sealed interface MaskStickerSet : StickerSet
|
||||||
|
@Serializable
|
||||||
|
sealed interface CustomEmojiStickerSet : StickerSet
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RegularSimpleStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<RegularSimpleSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : RegularStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.Regular
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RegularAnimatedStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<RegularAnimatedSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : RegularStickerSet, AnimatedStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.Regular
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RegularVideoStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<RegularVideoSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : RegularStickerSet, VideoStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.Regular
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MaskSimpleStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<MaskSimpleSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : MaskStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.Mask
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MaskAnimatedStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<MaskAnimatedSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : MaskStickerSet, AnimatedStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.Mask
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MaskVideoStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<MaskVideoSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : MaskStickerSet, VideoStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.Mask
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiSimpleStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<CustomEmojiSimpleSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : CustomEmojiStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.CustomEmoji
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiAnimatedStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<CustomEmojiAnimatedSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : CustomEmojiStickerSet, AnimatedStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.CustomEmoji
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class CustomEmojiVideoStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<CustomEmojiVideoSticker>,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null
|
||||||
|
) : CustomEmojiStickerSet, VideoStickerSet {
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
@EncodeDefault
|
||||||
|
override val stickerType: StickerType = StickerType.CustomEmoji
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class UnknownStickerSet(
|
||||||
|
@SerialName(nameField)
|
||||||
|
override val name: String,
|
||||||
|
@SerialName(titleField)
|
||||||
|
override val title: String,
|
||||||
|
@SerialName(stickersField)
|
||||||
|
override val stickers: List<Sticker>,
|
||||||
|
@SerialName(stickerTypeField)
|
||||||
|
override val stickerType: StickerType,
|
||||||
|
@SerialName(thumbField)
|
||||||
|
override val thumb: PhotoSize? = null,
|
||||||
|
val raw: JsonElement
|
||||||
|
) : CustomEmojiStickerSet, VideoStickerSet
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ internal fun String.commandMarkdown(): String = command(String::toMarkdown)
|
|||||||
internal fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
|
internal fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
|
||||||
internal fun String.commandHTML(): String = command(String::toHtml)
|
internal fun String.commandHTML(): String = command(String::toHtml)
|
||||||
|
|
||||||
|
internal fun String.customEmojiMarkdown(): String = toMarkdown()
|
||||||
|
internal fun String.customEmojiMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
|
internal fun String.customEmojiHTML(): String = toHtml()
|
||||||
|
|
||||||
internal fun String.regularMarkdown(): String = toMarkdown()
|
internal fun String.regularMarkdown(): String = toMarkdown()
|
||||||
internal fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
|
internal fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
internal fun String.regularHtml(): String = toHtml()
|
internal fun String.regularHtml(): String = toHtml()
|
||||||
|
|||||||
@@ -167,18 +167,30 @@ import dev.inmo.tgbotapi.types.dice.SlotMachineDiceAnimationType
|
|||||||
import dev.inmo.tgbotapi.types.files.AnimatedSticker
|
import dev.inmo.tgbotapi.types.files.AnimatedSticker
|
||||||
import dev.inmo.tgbotapi.types.files.AnimationFile
|
import dev.inmo.tgbotapi.types.files.AnimationFile
|
||||||
import dev.inmo.tgbotapi.types.files.AudioFile
|
import dev.inmo.tgbotapi.types.files.AudioFile
|
||||||
|
import dev.inmo.tgbotapi.types.files.CustomEmojiAnimatedSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.CustomEmojiSimpleSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.CustomEmojiSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.CustomEmojiVideoSticker
|
||||||
import dev.inmo.tgbotapi.types.files.DocumentFile
|
import dev.inmo.tgbotapi.types.files.DocumentFile
|
||||||
import dev.inmo.tgbotapi.types.files.File
|
import dev.inmo.tgbotapi.types.files.File
|
||||||
|
import dev.inmo.tgbotapi.types.files.MaskAnimatedSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.MaskSimpleSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.MaskSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.MaskVideoSticker
|
||||||
import dev.inmo.tgbotapi.types.files.MimedMediaFile
|
import dev.inmo.tgbotapi.types.files.MimedMediaFile
|
||||||
import dev.inmo.tgbotapi.types.files.PassportFile
|
import dev.inmo.tgbotapi.types.files.PassportFile
|
||||||
import dev.inmo.tgbotapi.types.files.PathedFile
|
import dev.inmo.tgbotapi.types.files.PathedFile
|
||||||
import dev.inmo.tgbotapi.types.files.PhotoSize
|
import dev.inmo.tgbotapi.types.files.PhotoSize
|
||||||
import dev.inmo.tgbotapi.types.files.PlayableMediaFile
|
import dev.inmo.tgbotapi.types.files.PlayableMediaFile
|
||||||
import dev.inmo.tgbotapi.types.files.SimpleSticker
|
import dev.inmo.tgbotapi.types.files.RegularAnimatedSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.RegularSimpleSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.RegularSticker
|
||||||
|
import dev.inmo.tgbotapi.types.files.RegularVideoSticker
|
||||||
import dev.inmo.tgbotapi.types.files.SizedMediaFile
|
import dev.inmo.tgbotapi.types.files.SizedMediaFile
|
||||||
import dev.inmo.tgbotapi.types.files.Sticker
|
import dev.inmo.tgbotapi.types.files.Sticker
|
||||||
import dev.inmo.tgbotapi.types.files.TelegramMediaFile
|
import dev.inmo.tgbotapi.types.files.TelegramMediaFile
|
||||||
import dev.inmo.tgbotapi.types.files.ThumbedMediaFile
|
import dev.inmo.tgbotapi.types.files.ThumbedMediaFile
|
||||||
|
import dev.inmo.tgbotapi.types.files.UnknownSticker
|
||||||
import dev.inmo.tgbotapi.types.files.VideoFile
|
import dev.inmo.tgbotapi.types.files.VideoFile
|
||||||
import dev.inmo.tgbotapi.types.files.VideoNoteFile
|
import dev.inmo.tgbotapi.types.files.VideoNoteFile
|
||||||
import dev.inmo.tgbotapi.types.files.VideoSticker
|
import dev.inmo.tgbotapi.types.files.VideoSticker
|
||||||
@@ -295,6 +307,7 @@ import dev.inmo.tgbotapi.types.message.textsources.BoldTextSource
|
|||||||
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.CashTagTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.CashTagTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.CodeTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.CodeTextSource
|
||||||
|
import dev.inmo.tgbotapi.types.message.textsources.CustomEmojiTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.HashTagTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.HashTagTextSource
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.ItalicTextSource
|
import dev.inmo.tgbotapi.types.message.textsources.ItalicTextSource
|
||||||
@@ -2266,14 +2279,14 @@ public inline fun TelegramMediaFile.stickerOrThrow(): Sticker = this as
|
|||||||
public inline fun <T> TelegramMediaFile.ifSticker(block: (Sticker) -> T): T? = stickerOrNull()
|
public inline fun <T> TelegramMediaFile.ifSticker(block: (Sticker) -> T): T? = stickerOrNull()
|
||||||
?.let(block)
|
?.let(block)
|
||||||
|
|
||||||
public inline fun TelegramMediaFile.simpleStickerOrNull(): SimpleSticker? = this as?
|
public inline fun TelegramMediaFile.videoStickerOrNull(): VideoSticker? = this as?
|
||||||
dev.inmo.tgbotapi.types.files.SimpleSticker
|
dev.inmo.tgbotapi.types.files.VideoSticker
|
||||||
|
|
||||||
public inline fun TelegramMediaFile.simpleStickerOrThrow(): SimpleSticker = this as
|
public inline fun TelegramMediaFile.videoStickerOrThrow(): VideoSticker = this as
|
||||||
dev.inmo.tgbotapi.types.files.SimpleSticker
|
dev.inmo.tgbotapi.types.files.VideoSticker
|
||||||
|
|
||||||
public inline fun <T> TelegramMediaFile.ifSimpleSticker(block: (SimpleSticker) -> T): T? =
|
public inline fun <T> TelegramMediaFile.ifVideoSticker(block: (VideoSticker) -> T): T? =
|
||||||
simpleStickerOrNull() ?.let(block)
|
videoStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
public inline fun TelegramMediaFile.animatedStickerOrNull(): AnimatedSticker? = this as?
|
public inline fun TelegramMediaFile.animatedStickerOrNull(): AnimatedSticker? = this as?
|
||||||
dev.inmo.tgbotapi.types.files.AnimatedSticker
|
dev.inmo.tgbotapi.types.files.AnimatedSticker
|
||||||
@@ -2284,14 +2297,126 @@ public inline fun TelegramMediaFile.animatedStickerOrThrow(): AnimatedSticker =
|
|||||||
public inline fun <T> TelegramMediaFile.ifAnimatedSticker(block: (AnimatedSticker) -> T): T? =
|
public inline fun <T> TelegramMediaFile.ifAnimatedSticker(block: (AnimatedSticker) -> T): T? =
|
||||||
animatedStickerOrNull() ?.let(block)
|
animatedStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
public inline fun TelegramMediaFile.videoStickerOrNull(): VideoSticker? = this as?
|
public inline fun TelegramMediaFile.regularStickerOrNull(): RegularSticker? = this as?
|
||||||
dev.inmo.tgbotapi.types.files.VideoSticker
|
dev.inmo.tgbotapi.types.files.RegularSticker
|
||||||
|
|
||||||
public inline fun TelegramMediaFile.videoStickerOrThrow(): VideoSticker = this as
|
public inline fun TelegramMediaFile.regularStickerOrThrow(): RegularSticker = this as
|
||||||
dev.inmo.tgbotapi.types.files.VideoSticker
|
dev.inmo.tgbotapi.types.files.RegularSticker
|
||||||
|
|
||||||
public inline fun <T> TelegramMediaFile.ifVideoSticker(block: (VideoSticker) -> T): T? =
|
public inline fun <T> TelegramMediaFile.ifRegularSticker(block: (RegularSticker) -> T): T? =
|
||||||
videoStickerOrNull() ?.let(block)
|
regularStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.regularSimpleStickerOrNull(): RegularSimpleSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.RegularSimpleSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.regularSimpleStickerOrThrow(): RegularSimpleSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.RegularSimpleSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifRegularSimpleSticker(block: (RegularSimpleSticker) -> T):
|
||||||
|
T? = regularSimpleStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.regularAnimatedStickerOrNull(): RegularAnimatedSticker? = this
|
||||||
|
as? dev.inmo.tgbotapi.types.files.RegularAnimatedSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.regularAnimatedStickerOrThrow(): RegularAnimatedSticker = this
|
||||||
|
as dev.inmo.tgbotapi.types.files.RegularAnimatedSticker
|
||||||
|
|
||||||
|
public inline fun <T>
|
||||||
|
TelegramMediaFile.ifRegularAnimatedSticker(block: (RegularAnimatedSticker) -> T): T? =
|
||||||
|
regularAnimatedStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.regularVideoStickerOrNull(): RegularVideoSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.RegularVideoSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.regularVideoStickerOrThrow(): RegularVideoSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.RegularVideoSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifRegularVideoSticker(block: (RegularVideoSticker) -> T): T?
|
||||||
|
= regularVideoStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskStickerOrNull(): MaskSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskStickerOrThrow(): MaskSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifMaskSticker(block: (MaskSticker) -> T): T? =
|
||||||
|
maskStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskSimpleStickerOrNull(): MaskSimpleSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskSimpleSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskSimpleStickerOrThrow(): MaskSimpleSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskSimpleSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifMaskSimpleSticker(block: (MaskSimpleSticker) -> T): T? =
|
||||||
|
maskSimpleStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskAnimatedStickerOrNull(): MaskAnimatedSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskAnimatedSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskAnimatedStickerOrThrow(): MaskAnimatedSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskAnimatedSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifMaskAnimatedSticker(block: (MaskAnimatedSticker) -> T): T?
|
||||||
|
= maskAnimatedStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskVideoStickerOrNull(): MaskVideoSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskVideoSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.maskVideoStickerOrThrow(): MaskVideoSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.MaskVideoSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifMaskVideoSticker(block: (MaskVideoSticker) -> T): T? =
|
||||||
|
maskVideoStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiStickerOrNull(): CustomEmojiSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.CustomEmojiSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiStickerOrThrow(): CustomEmojiSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.CustomEmojiSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifCustomEmojiSticker(block: (CustomEmojiSticker) -> T): T? =
|
||||||
|
customEmojiStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiSimpleStickerOrNull(): CustomEmojiSimpleSticker? =
|
||||||
|
this as? dev.inmo.tgbotapi.types.files.CustomEmojiSimpleSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiSimpleStickerOrThrow(): CustomEmojiSimpleSticker =
|
||||||
|
this as dev.inmo.tgbotapi.types.files.CustomEmojiSimpleSticker
|
||||||
|
|
||||||
|
public inline fun <T>
|
||||||
|
TelegramMediaFile.ifCustomEmojiSimpleSticker(block: (CustomEmojiSimpleSticker) -> T): T? =
|
||||||
|
customEmojiSimpleStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiAnimatedStickerOrNull(): CustomEmojiAnimatedSticker?
|
||||||
|
= this as? dev.inmo.tgbotapi.types.files.CustomEmojiAnimatedSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiAnimatedStickerOrThrow(): CustomEmojiAnimatedSticker
|
||||||
|
= this as dev.inmo.tgbotapi.types.files.CustomEmojiAnimatedSticker
|
||||||
|
|
||||||
|
public inline fun <T>
|
||||||
|
TelegramMediaFile.ifCustomEmojiAnimatedSticker(block: (CustomEmojiAnimatedSticker) -> T): T? =
|
||||||
|
customEmojiAnimatedStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiVideoStickerOrNull(): CustomEmojiVideoSticker? = this
|
||||||
|
as? dev.inmo.tgbotapi.types.files.CustomEmojiVideoSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.customEmojiVideoStickerOrThrow(): CustomEmojiVideoSticker = this
|
||||||
|
as dev.inmo.tgbotapi.types.files.CustomEmojiVideoSticker
|
||||||
|
|
||||||
|
public inline fun <T>
|
||||||
|
TelegramMediaFile.ifCustomEmojiVideoSticker(block: (CustomEmojiVideoSticker) -> T): T? =
|
||||||
|
customEmojiVideoStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.unknownStickerOrNull(): UnknownSticker? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.files.UnknownSticker
|
||||||
|
|
||||||
|
public inline fun TelegramMediaFile.unknownStickerOrThrow(): UnknownSticker = this as
|
||||||
|
dev.inmo.tgbotapi.types.files.UnknownSticker
|
||||||
|
|
||||||
|
public inline fun <T> TelegramMediaFile.ifUnknownSticker(block: (UnknownSticker) -> T): T? =
|
||||||
|
unknownStickerOrNull() ?.let(block)
|
||||||
|
|
||||||
public inline fun TelegramMediaFile.thumbedMediaFileOrNull(): ThumbedMediaFile? = this as?
|
public inline fun TelegramMediaFile.thumbedMediaFileOrNull(): ThumbedMediaFile? = this as?
|
||||||
dev.inmo.tgbotapi.types.files.ThumbedMediaFile
|
dev.inmo.tgbotapi.types.files.ThumbedMediaFile
|
||||||
@@ -3427,6 +3552,15 @@ public inline fun TextSource.codeTextSourceOrThrow(): CodeTextSource = this as
|
|||||||
public inline fun <T> TextSource.ifCodeTextSource(block: (CodeTextSource) -> T): T? =
|
public inline fun <T> TextSource.ifCodeTextSource(block: (CodeTextSource) -> T): T? =
|
||||||
codeTextSourceOrNull() ?.let(block)
|
codeTextSourceOrNull() ?.let(block)
|
||||||
|
|
||||||
|
public inline fun TextSource.customEmojiTextSourceOrNull(): CustomEmojiTextSource? = this as?
|
||||||
|
dev.inmo.tgbotapi.types.message.textsources.CustomEmojiTextSource
|
||||||
|
|
||||||
|
public inline fun TextSource.customEmojiTextSourceOrThrow(): CustomEmojiTextSource = this as
|
||||||
|
dev.inmo.tgbotapi.types.message.textsources.CustomEmojiTextSource
|
||||||
|
|
||||||
|
public inline fun <T> TextSource.ifCustomEmojiTextSource(block: (CustomEmojiTextSource) -> T): T? =
|
||||||
|
customEmojiTextSourceOrNull() ?.let(block)
|
||||||
|
|
||||||
public inline fun TextSource.eMailTextSourceOrNull(): EMailTextSource? = this as?
|
public inline fun TextSource.eMailTextSourceOrNull(): EMailTextSource? = this as?
|
||||||
dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
dev.inmo.tgbotapi.types.message.textsources.EMailTextSource
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ fun <T> Flow<Iterable<T>>.flatten(): Flow<T> = flow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T, R> Flow<T>.flatMap(mapper: (T) -> Iterable<R>): Flow<R> = flow {
|
fun <T, R> Flow<T>.flatMap(mapper: suspend (T) -> Iterable<R>): Flow<R> = flow {
|
||||||
collect {
|
collect {
|
||||||
mapper(it).forEach {
|
mapper(it).forEach {
|
||||||
emit(it)
|
emit(it)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.extensions.raw
|
package dev.inmo.tgbotapi.extensions.utils.extensions.raw
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.*
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||||
import dev.inmo.tgbotapi.types.FileUniqueId
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.StickerSetName
|
|
||||||
import dev.inmo.tgbotapi.types.files.*
|
import dev.inmo.tgbotapi.types.files.*
|
||||||
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
import dev.inmo.tgbotapi.types.stickers.MaskPosition
|
||||||
|
|
||||||
@@ -17,8 +17,10 @@ inline val Sticker.is_video: Boolean
|
|||||||
inline val Sticker.set_name: StickerSetName?
|
inline val Sticker.set_name: StickerSetName?
|
||||||
get() = stickerSetName
|
get() = stickerSetName
|
||||||
inline val Sticker.mask_position: MaskPosition?
|
inline val Sticker.mask_position: MaskPosition?
|
||||||
get() = maskPosition
|
get() = maskStickerOrNull() ?.maskPosition
|
||||||
inline val Sticker.file_size: Long?
|
inline val Sticker.file_size: Long?
|
||||||
get() = fileSize
|
get() = fileSize
|
||||||
inline val Sticker.premium_animation: File?
|
inline val Sticker.premium_animation: File?
|
||||||
get() = premiumAnimationFile
|
get() = regularStickerOrNull() ?.premiumAnimationFile
|
||||||
|
inline val Sticker.custom_emoji_id: CustomEmojiId?
|
||||||
|
get() = customEmojiStickerOrNull() ?.customEmojiId
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.formatting
|
package dev.inmo.tgbotapi.extensions.utils.formatting
|
||||||
|
|
||||||
import dev.inmo.micro_utils.common.joinTo
|
import dev.inmo.micro_utils.common.joinTo
|
||||||
|
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.*
|
import dev.inmo.tgbotapi.types.message.textsources.*
|
||||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
@@ -510,3 +511,39 @@ inline fun EntitiesBuilder.underline(text: String) = add(dev.inmo.tgbotapi.types
|
|||||||
* Version of [EntitiesBuilder.underline] with new line at the end
|
* Version of [EntitiesBuilder.underline] with new line at the end
|
||||||
*/
|
*/
|
||||||
inline fun EntitiesBuilder.underlineln(text: String) = underline(text) + newLine
|
inline fun EntitiesBuilder.underlineln(text: String) = underline(text) + newLine
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, parts))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, parts: TextSourcesList) = customEmoji(customEmojiId, parts) + newLine
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji].
|
||||||
|
* Will reuse separator config from [buildEntities]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, buildEntities(separator, init)))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end.
|
||||||
|
* Will reuse separator config from [buildEntities]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, noinline init: EntitiesBuilderBody) = customEmoji(customEmojiId, init) + newLine
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, *parts))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, vararg parts: TextSource) = customEmoji(customEmojiId, *parts) + newLine
|
||||||
|
/**
|
||||||
|
* Add customEmoji using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.customEmoji]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmoji(customEmojiId: CustomEmojiId, text: String) = add(dev.inmo.tgbotapi.types.message.textsources.customEmoji(customEmojiId, text))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.customEmoji] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.customEmojiln(customEmojiId: CustomEmojiId, text: String) = customEmoji(customEmojiId, text) + newLine
|
||||||
|
|||||||
@@ -4,17 +4,25 @@ import dev.inmo.tgbotapi.types.*
|
|||||||
import dev.inmo.tgbotapi.types.chat.*
|
import dev.inmo.tgbotapi.types.chat.*
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
||||||
import dev.inmo.tgbotapi.types.message.textsources.link
|
import dev.inmo.tgbotapi.types.message.textsources.link
|
||||||
|
import io.ktor.http.encodeURLQueryComponent
|
||||||
|
|
||||||
|
|
||||||
fun makeUsernameLink(username: String) = "$internalLinkBeginning/$username"
|
fun makeUsernameLink(username: String) = "$internalLinkBeginning/$username"
|
||||||
fun makeUsernameDeepLinkPrefix(username: String) = "${makeUsernameLink(username)}?start="
|
fun makeUsernameDeepLinkPrefix(username: String) = "${makeUsernameLink(username)}?start="
|
||||||
|
fun makeUsernameStartattachPrefix(username: String) = "$internalLinkBeginning/$username?startattach"
|
||||||
|
fun makeUsernameStartattachLink(username: String, data: String? = null) = "${makeUsernameStartattachPrefix(username)}${data?.let { "=$it" } ?: ""}"
|
||||||
inline val Username.link
|
inline val Username.link
|
||||||
get() = makeUsernameLink(usernameWithoutAt)
|
get() = makeUsernameLink(usernameWithoutAt)
|
||||||
inline val Username.deepLinkPrefix
|
inline val Username.deepLinkPrefix
|
||||||
get() = makeUsernameDeepLinkPrefix(usernameWithoutAt)
|
get() = makeUsernameDeepLinkPrefix(usernameWithoutAt)
|
||||||
|
inline val Username.startattachPrefix
|
||||||
|
get() = makeUsernameStartattachPrefix(usernameWithoutAt)
|
||||||
inline fun makeLink(username: Username) = username.link
|
inline fun makeLink(username: Username) = username.link
|
||||||
inline fun makeTelegramDeepLink(username: String, startParameter: String) = "${makeUsernameDeepLinkPrefix(username)}$startParameter"
|
inline fun makeTelegramDeepLink(username: String, startParameter: String) = "${makeUsernameDeepLinkPrefix(username)}$startParameter".encodeURLQueryComponent()
|
||||||
inline fun makeDeepLink(username: Username, startParameter: String) = "${username.deepLinkPrefix}$startParameter"
|
inline fun makeTelegramStartattach(username: String, data: String? = null) = makeUsernameStartattachLink(username, data)
|
||||||
|
inline fun makeDeepLink(username: Username, startParameter: String) = makeTelegramDeepLink(username.usernameWithoutAt, startParameter)
|
||||||
inline fun makeTelegramDeepLink(username: Username, startParameter: String) = makeDeepLink(username, startParameter)
|
inline fun makeTelegramDeepLink(username: Username, startParameter: String) = makeDeepLink(username, startParameter)
|
||||||
|
inline fun makeTelegramStartattach(username: Username, data: String? = null) = makeTelegramStartattach(username.usernameWithoutAt, data)
|
||||||
|
|
||||||
fun makeLinkToMessage(
|
fun makeLinkToMessage(
|
||||||
username: String,
|
username: String,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.*
|
|||||||
fun TelegramBot.longPollingFlow(
|
fun TelegramBot.longPollingFlow(
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
): Flow<Update> = channelFlow {
|
): Flow<Update> = channelFlow {
|
||||||
var lastUpdateIdentifier: UpdateIdentifier? = null
|
var lastUpdateIdentifier: UpdateIdentifier? = null
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
updatesReceiver: UpdateReceiver<Update>
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
): Job = longPollingFlow(timeoutSeconds, exceptionsHandler, allowedUpdates).subscribeSafely(
|
): Job = longPollingFlow(timeoutSeconds, exceptionsHandler, allowedUpdates).subscribeSafely(
|
||||||
scope,
|
scope,
|
||||||
@@ -97,7 +97,7 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
|
|||||||
avoidInlineQueries: Boolean = false,
|
avoidInlineQueries: Boolean = false,
|
||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
allowedUpdates: List<String>? = null
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST
|
||||||
): Flow<Update> = longPollingFlow(
|
): Flow<Update> = longPollingFlow(
|
||||||
timeoutSeconds = 0,
|
timeoutSeconds = 0,
|
||||||
exceptionsHandler = {
|
exceptionsHandler = {
|
||||||
@@ -117,7 +117,7 @@ fun TelegramBot.retrieveAccumulatedUpdates(
|
|||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
updatesReceiver: UpdateReceiver<Update>
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
): Job = createAccumulatedUpdatesRetrieverFlow(
|
): Job = createAccumulatedUpdatesRetrieverFlow(
|
||||||
avoidInlineQueries,
|
avoidInlineQueries,
|
||||||
@@ -149,7 +149,7 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
|
|||||||
avoidInlineQueries: Boolean = false,
|
avoidInlineQueries: Boolean = false,
|
||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
updatesReceiver: UpdateReceiver<Update> = {}
|
updatesReceiver: UpdateReceiver<Update> = {}
|
||||||
) = retrieveAccumulatedUpdates(
|
) = retrieveAccumulatedUpdates(
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps
|
||||||
|
|
||||||
|
typealias AlertCallback = () -> Unit
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps
|
||||||
|
|
||||||
|
typealias ConfirmCallback = (confirmed: Boolean) -> Unit
|
||||||
@@ -5,3 +5,4 @@ import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
|
|||||||
typealias EventHandler = WebApp.() -> Unit
|
typealias EventHandler = WebApp.() -> Unit
|
||||||
typealias ViewportChangedEventHandler = WebApp.(ViewportChangedData) -> Unit
|
typealias ViewportChangedEventHandler = WebApp.(ViewportChangedData) -> Unit
|
||||||
typealias InvoiceClosedEventHandler = WebApp.(InvoiceClosedInfo) -> Unit
|
typealias InvoiceClosedEventHandler = WebApp.(InvoiceClosedInfo) -> Unit
|
||||||
|
typealias PopupClosedEventHandler = WebApp.(String?) -> Unit
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ sealed class EventType(val typeName: String) {
|
|||||||
object BackButtonClicked : EventType("backButtonClicked")
|
object BackButtonClicked : EventType("backButtonClicked")
|
||||||
object SettingsButtonClicked : EventType("settingsButtonClicked")
|
object SettingsButtonClicked : EventType("settingsButtonClicked")
|
||||||
object InvoiceClosed : EventType("invoiceClosed")
|
object InvoiceClosed : EventType("invoiceClosed")
|
||||||
|
object PopupClosed : EventType("popupClosed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.webapps
|
|||||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||||
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedback
|
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedback
|
||||||
import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
|
import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
|
||||||
|
import dev.inmo.tgbotapi.webapps.popup.*
|
||||||
|
|
||||||
external class WebApp {
|
external class WebApp {
|
||||||
val version: String
|
val version: String
|
||||||
@@ -24,6 +25,15 @@ external class WebApp {
|
|||||||
val viewportHeight: Float
|
val viewportHeight: Float
|
||||||
val viewportStableHeight: Float
|
val viewportStableHeight: Float
|
||||||
|
|
||||||
|
|
||||||
|
val isClosingConfirmationEnabled: Boolean
|
||||||
|
fun enableClosingConfirmation()
|
||||||
|
fun disableClosingConfirmation()
|
||||||
|
|
||||||
|
fun showPopup(params: PopupParams, callback: ClosePopupCallback? = definedExternally)
|
||||||
|
fun showAlert(message: String, callback: AlertCallback? = definedExternally)
|
||||||
|
fun showConfirm(message: String, callback: ConfirmCallback? = definedExternally)
|
||||||
|
|
||||||
@JsName("MainButton")
|
@JsName("MainButton")
|
||||||
val mainButton: MainButton
|
val mainButton: MainButton
|
||||||
|
|
||||||
@@ -38,6 +48,8 @@ external class WebApp {
|
|||||||
internal fun onEventWithViewportChangedData(type: String, callback: (ViewportChangedData) -> Unit)
|
internal fun onEventWithViewportChangedData(type: String, callback: (ViewportChangedData) -> Unit)
|
||||||
@JsName("onEvent")
|
@JsName("onEvent")
|
||||||
internal fun onEventWithInvoiceClosedInfo(type: String, callback: (InvoiceClosedInfo) -> Unit)
|
internal fun onEventWithInvoiceClosedInfo(type: String, callback: (InvoiceClosedInfo) -> Unit)
|
||||||
|
@JsName("onEvent")
|
||||||
|
internal fun onEventWithPopupClosedInfo(type: String, callback: (String?) -> Unit)
|
||||||
|
|
||||||
fun offEvent(type: String, callback: () -> Unit)
|
fun offEvent(type: String, callback: () -> Unit)
|
||||||
@JsName("offEvent")
|
@JsName("offEvent")
|
||||||
@@ -100,6 +112,18 @@ fun WebApp.onEvent(type: EventType.InvoiceClosed, eventHandler: InvoiceClosedEve
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The callback which should be used in case you want to turn off events handling
|
||||||
|
*/
|
||||||
|
fun WebApp.onEvent(type: EventType.PopupClosed, eventHandler: PopupClosedEventHandler) = { it: String? ->
|
||||||
|
eventHandler(js("this").unsafeCast<WebApp>(), it)
|
||||||
|
}.also {
|
||||||
|
onEventWithPopupClosedInfo(
|
||||||
|
type.typeName,
|
||||||
|
callback = it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The callback which should be used in case you want to turn off events handling
|
* @return The callback which should be used in case you want to turn off events handling
|
||||||
*/
|
*/
|
||||||
@@ -124,8 +148,55 @@ fun WebApp.onSettingsButtonClicked(eventHandler: EventHandler) = onEvent(EventTy
|
|||||||
* @return The callback which should be used in case you want to turn off events handling
|
* @return The callback which should be used in case you want to turn off events handling
|
||||||
*/
|
*/
|
||||||
fun WebApp.onInvoiceClosed(eventHandler: InvoiceClosedEventHandler) = onEvent(EventType.InvoiceClosed, eventHandler)
|
fun WebApp.onInvoiceClosed(eventHandler: InvoiceClosedEventHandler) = onEvent(EventType.InvoiceClosed, eventHandler)
|
||||||
|
/**
|
||||||
|
* @return The callback which should be used in case you want to turn off events handling
|
||||||
|
*/
|
||||||
|
fun WebApp.onPopupClosed(eventHandler: PopupClosedEventHandler) = onEvent(EventType.PopupClosed, eventHandler)
|
||||||
|
|
||||||
fun WebApp.isInitDataSafe(botToken: String) = TelegramAPIUrlsKeeper(botToken).checkWebAppData(
|
fun WebApp.isInitDataSafe(botToken: String) = TelegramAPIUrlsKeeper(botToken).checkWebAppData(
|
||||||
initData,
|
initData,
|
||||||
initDataUnsafe.hash
|
initDataUnsafe.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun WebApp.showPopup(
|
||||||
|
message: String,
|
||||||
|
title: String?,
|
||||||
|
buttons: Array<PopupButton>,
|
||||||
|
callback: ClosePopupCallback? = null
|
||||||
|
) = showPopup(
|
||||||
|
PopupParams(
|
||||||
|
message,
|
||||||
|
title,
|
||||||
|
buttons
|
||||||
|
),
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
|
||||||
|
fun WebApp.showPopup(
|
||||||
|
message: String,
|
||||||
|
title: String?,
|
||||||
|
firstButton: PopupButton,
|
||||||
|
vararg otherButtons: PopupButton,
|
||||||
|
callback: ClosePopupCallback? = null
|
||||||
|
) = showPopup(
|
||||||
|
PopupParams(
|
||||||
|
message,
|
||||||
|
title,
|
||||||
|
arrayOf(firstButton, *otherButtons)
|
||||||
|
),
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
|
||||||
|
var WebApp.requireClosingConfirmation
|
||||||
|
get() = isClosingConfirmationEnabled
|
||||||
|
set(value) {
|
||||||
|
if (value) {
|
||||||
|
enableClosingConfirmation()
|
||||||
|
} else {
|
||||||
|
disableClosingConfirmation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun WebApp.toggleClosingConfirmation() {
|
||||||
|
requireClosingConfirmation = !requireClosingConfirmation
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,10 +17,14 @@ external interface WebAppUser {
|
|||||||
val username: String?
|
val username: String?
|
||||||
@JsName(languageCodeField)
|
@JsName(languageCodeField)
|
||||||
val languageCode: String?
|
val languageCode: String?
|
||||||
|
val is_premium: Boolean?
|
||||||
@JsName(photoUrlField)
|
@JsName(photoUrlField)
|
||||||
val photoUrl: String?
|
val photoUrl: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val WebAppUser.isPremium
|
||||||
|
get() = is_premium == true
|
||||||
|
|
||||||
fun WebAppUser.asUser() = if (isBot == true) {
|
fun WebAppUser.asUser() = if (isBot == true) {
|
||||||
CommonBot(
|
CommonBot(
|
||||||
UserId(id),
|
UserId(id),
|
||||||
@@ -34,6 +38,7 @@ fun WebAppUser.asUser() = if (isBot == true) {
|
|||||||
firstName,
|
firstName,
|
||||||
lastName ?: "",
|
lastName ?: "",
|
||||||
username ?.let(::Username),
|
username ?.let(::Username),
|
||||||
languageCode ?.let(::IetfLanguageCode)
|
languageCode ?.let(::IetfLanguageCode),
|
||||||
|
isPremium = isPremium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.popup
|
||||||
|
|
||||||
|
typealias ClosePopupCallback = (id: String) -> Unit
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.popup
|
||||||
|
|
||||||
|
import kotlin.js.json
|
||||||
|
|
||||||
|
external interface PopupButton {
|
||||||
|
val id: String
|
||||||
|
val type: PopupButtonType
|
||||||
|
val text: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PopupButton(
|
||||||
|
id: String,
|
||||||
|
type: PopupButtonType,
|
||||||
|
text: String? = null
|
||||||
|
) = json(
|
||||||
|
*listOfNotNull(
|
||||||
|
"id" to id,
|
||||||
|
"type" to type.typeName,
|
||||||
|
("text" to text).takeIf { text != null }
|
||||||
|
).toTypedArray()
|
||||||
|
).unsafeCast<PopupButton>()
|
||||||
|
|
||||||
|
value class PopupButtonType(
|
||||||
|
val typeName: String
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
val Default = PopupButtonType("default")
|
||||||
|
val Ok = PopupButtonType("ok")
|
||||||
|
val Close = PopupButtonType("close")
|
||||||
|
val Cancel = PopupButtonType("cancel")
|
||||||
|
val Destructive = PopupButtonType("destructive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DefaultPopupButton(
|
||||||
|
id: String,
|
||||||
|
text: String
|
||||||
|
) = PopupButton(id, PopupButtonType.Default, text)
|
||||||
|
|
||||||
|
fun OkPopupButton(
|
||||||
|
id: String
|
||||||
|
) = PopupButton(id, PopupButtonType.Ok)
|
||||||
|
|
||||||
|
fun ClosePopupButton(
|
||||||
|
id: String
|
||||||
|
) = PopupButton(id, PopupButtonType.Close)
|
||||||
|
|
||||||
|
fun CancelPopupButton(
|
||||||
|
id: String
|
||||||
|
) = PopupButton(id, PopupButtonType.Cancel)
|
||||||
|
|
||||||
|
fun DestructivePopupButton(
|
||||||
|
id: String,
|
||||||
|
text: String
|
||||||
|
) = PopupButton(id, PopupButtonType.Destructive, text)
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.popup
|
||||||
|
|
||||||
|
import kotlin.js.json
|
||||||
|
|
||||||
|
external interface PopupParams {
|
||||||
|
val message: String
|
||||||
|
val title: String?
|
||||||
|
val buttons: Array<PopupButton>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PopupParams(
|
||||||
|
message: String,
|
||||||
|
title: String?,
|
||||||
|
buttons: Array<PopupButton>
|
||||||
|
) = json(
|
||||||
|
*listOfNotNull(
|
||||||
|
"message" to message,
|
||||||
|
"buttons" to buttons,
|
||||||
|
("title" to title).takeIf { title != null }
|
||||||
|
).toTypedArray()
|
||||||
|
).unsafeCast<PopupParams>()
|
||||||
|
|
||||||
|
fun PopupParams(
|
||||||
|
message: String,
|
||||||
|
firstButton: PopupButton,
|
||||||
|
vararg otherButtons: PopupButton
|
||||||
|
) = PopupParams(
|
||||||
|
message,
|
||||||
|
null,
|
||||||
|
arrayOf(
|
||||||
|
firstButton,
|
||||||
|
*otherButtons
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun PopupParams(
|
||||||
|
title: String,
|
||||||
|
message: String,
|
||||||
|
firstButton: PopupButton,
|
||||||
|
vararg otherButtons: PopupButton
|
||||||
|
) = PopupParams(
|
||||||
|
message,
|
||||||
|
title,
|
||||||
|
arrayOf(
|
||||||
|
firstButton,
|
||||||
|
*otherButtons
|
||||||
|
)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user