1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-30 11:25:44 +00:00

Compare commits

..

54 Commits

Author SHA1 Message Date
41e5c579a2 add excluding of CHANGELOG file for labeler 2020-06-26 17:45:16 +06:00
bbf63c51ec Revert "add com.soywiz.korlibs.krypto:krypto dependency"
This reverts commit acfb7066d2.
2020-06-25 15:45:38 +06:00
fb91199f83 Revert "start implement passport"
This reverts commit d76c09ffb2.
2020-06-25 15:45:35 +06:00
d76c09ffb2 start implement passport 2020-06-25 15:45:15 +06:00
acfb7066d2 add com.soywiz.korlibs.krypto:krypto dependency 2020-06-25 12:07:48 +06:00
7507c107b4 add one more flatMatrix 2020-06-24 20:54:22 +06:00
2acb177ad6 first keyboards improvements 2020-06-24 20:51:48 +06:00
b5a14077fd start 0.27.7 2020-06-24 20:25:51 +06:00
5f60bf003f Add useful links 2020-06-07 17:27:20 +06:00
f9b2c4c403 update README 2020-06-05 17:01:37 +06:00
c909774403 Merge pull request #91 from InsanusMokrassar/0.27.6
0.27.6
2020-06-05 15:44:30 +06:00
670cfcca13 update kotlin coroutines 2020-06-05 15:17:14 +06:00
130e00b62b extensions for CommonMessage 2020-06-05 14:57:58 +06:00
ca4beee95f add PossiblySentViaBotCommonMessage and fix error in build 2020-06-05 14:25:19 +06:00
ca784e67df add BuiltInMimeTypes, ThumbedWithMimeTypeInlineQueryResult and buildMimeType factory 2020-06-05 14:01:19 +06:00
835b8b34f9 add via_bot 2020-06-05 13:40:12 +06:00
e6430a729c work on version 0.27.6 has been started 2020-06-05 13:37:11 +06:00
6c4c9f2fc6 by default dokka task will not set up exact folder for docs 2020-06-03 15:42:00 +06:00
310a7e6e82 update docs build gradle to be able to put dokka where it is required 2020-06-03 15:39:54 +06:00
7375894645 Merge pull request #90 from InsanusMokrassar/0.27.5
0.27.5
2020-06-02 22:26:07 +06:00
69973c597b update BotCommandNameRegex 2020-06-02 22:10:33 +06:00
22e8b06fda BotBuilder fixes 2020-06-02 21:18:49 +06:00
7ede53fdbb BotCommandNameRegex and strict check of incoming command 2020-06-02 20:16:55 +06:00
ca9051920d new setMyCommands extension added 2020-06-02 19:54:13 +06:00
b477e8d585 extend getChat extensions 2020-06-02 13:54:30 +06:00
8ae2f57d55 update description of PreviewFeature annotation 2020-06-02 13:47:28 +06:00
1fb2ecf15f executes was replaced 2020-06-02 13:39:09 +06:00
6073d914d5 hotfixes in new media groups shortcuts 2020-06-02 13:22:36 +06:00
16f55d70af resend and other media group utils replaced into TelegramBotAPI_extensions-utils 2020-06-02 13:21:38 +06:00
b484a31a4a replacement of CaptionAndTextSourcesToText 2020-06-02 13:05:15 +06:00
0a162c4129 StringFormattiing replacement 2020-06-02 01:26:46 +06:00
648f1b488b add makeLinkToAddStickerSet 2020-06-02 01:15:08 +06:00
5fbde4bc06 new "row" 2020-06-02 01:02:38 +06:00
2a276d9272 safely function 2020-06-01 12:56:48 +06:00
9ae252717d versions update 2020-06-01 12:00:06 +06:00
456143a266 complete refresh of CaptinAndTextSourcesToText 2020-06-01 11:55:48 +06:00
0bcc98e126 update caption errors 2020-06-01 11:53:33 +06:00
ab9ceba41c updates in caption and text lengths 2020-06-01 11:44:58 +06:00
7cd5666e88 use maxTextLength inside of CaptionAndTextSourcesToText 2020-05-31 22:53:04 +06:00
35dcd6ada7 fix in SendMessage 2020-05-31 22:51:42 +06:00
ec37df82a9 start 0.27.5 2020-05-31 22:43:35 +06:00
220cb47615 update look like of kdocs badge 2020-05-23 15:46:49 +06:00
d79b8a337a add kdocs badge 2020-05-23 15:43:47 +06:00
cef6a6f741 update telegram badge 2020-05-23 15:27:45 +06:00
9471df1f2d Merge pull request #89 from InsanusMokrassar/0.27.4
0.27.4
2020-05-23 15:22:13 +06:00
f121e5f9c3 renames for JVM signature duplication avoiding 2020-05-23 12:53:42 +06:00
7f4fe318c5 update filters 2020-05-22 16:40:30 +06:00
dbf5c2dbb2 update publish scripts 2020-05-22 14:03:48 +06:00
105415873d updates extensions 2020-05-22 13:21:22 +06:00
ff32fd1dfc 0.27.4 started 2020-05-22 12:56:50 +06:00
006251ed07 fixes 2020-05-17 15:10:02 +06:00
9307582654 Add TelegramBotAPI-all status to readme 2020-05-17 01:30:05 +06:00
fe11a2119e Return opts in telegram bot api 2020-05-16 22:24:50 +06:00
c31403c1a2 Merge pull request #88 from InsanusMokrassar/0.27.3
0.27.3
2020-05-16 22:07:56 +06:00
65 changed files with 1362 additions and 205 deletions

4
.github/labeler.yml vendored
View File

@@ -4,4 +4,6 @@ core: "TelegramBotAPI/**" # currently not work
code: "**/*.kt"
gradle: "**/*.gradle"
markdown: "**/*.md"
markdown:
- "**/*.md"
- "!CHANGELOG.md"

View File

@@ -49,6 +49,86 @@
* `closePollExactAfter`
* `closePollAfter`
### 0.27.7
* `TelegramBotAPI`:
* Operator function `unaryPlus` was added to `RowBuilder`. Now it is possible to write `row { +button }`
* Function `flatMatrix` was added for single-row columns
* Operator extension `RowBuilder#plus` was added to be able to write things like `row { this + button }`
* `TelegramBotAPI-extensions-utils`:
* Function `InlineKeyboardMarkup` for flat keyboards was added
* Function `ReplyKeyboardMarkup` for flat keyboards was added
### 0.27.6
* `Common`:
* Versions:
* `Kotlin Coroutines`: `1.3.6` -> `1.3.7`
* `TelegramBotAPI`:
* Interface `PossiblySentViaBot` has been added
* Additional interface `PossiblySentViaBotCommonMessage` was added for more explicit typing declaration for
compiler
* Currently, only `ChannelMessage` and `CommonMessageImpl` are implementing the interface
`PossiblySentViaBotCommonMessage`. It could be changed in future
* Factory `buildMimeType` was added
* `BuiltinMimeTypes` was added
* Abstraction `ThumbedWithMimeTypeInlineQueryResult` with `thumbMimeType` field was added
* `InlineQueryResultGif` and `InlineQueryResultMpeg4Gif` now extend `ThumbedWithMimeTypeInlineQueryResult`
instead of `ThumbedInlineQueryResult`
* `TelegramBotAPI-extensions-utils`:
* New extensions `onlyCommonMessages`, `onlySentViaBot` and `withoutSentViaBot` was added
### 0.27.5
* `Common`:
* Versions:
* `Klock`: `1.11.1` -> `1.11.3`
* `TelegramotAPI`:
* Fix: for sending requests caption and text lengths limits were updated
* New variant of `row` was added
* `makeLinkToMessage` extensions has been deprecated (replaced into `TelegramBotAPI-extensions-utils`)
* Next things was deprecated and replaced into `TelegramBotAPI-extensions-utils`:
* All `String` formatting public extensions and functions
* All extensions like `CaptionedInput#toHtmlCaptions`
* All helper extensions for `List<BaseMessageUpdate>`
* All `RequestsExecutor#executeAsync` and `RequestsExecutor#executeUnsafe`
* `BotCommand` now more strictly check commands which passed to it
* Regex `BotCommandNameRegex` was added
* `TelegramBotAPI-extensions-api`:
* A lot of `RequesstExecutor#getChat` extensions was added for more explicit types showing
* New `RequesstExecutor#setMyCommands` extension was added
* New field `BotBuilder#ktorClientEngineFactory` introduced
* Field `BotBuilder#ktorClientEngine` now is deprecated
* `TelegramBotAPI-extensions-utils`:
* `safely` function was introduced. It is in `PreviewFeature` state currently
* `makeLinkToMessage` extensions has been added
* `makeLinkToAddStickerSet` function and its variations were added
* Next tools was added from `TelegramBotAPI`:
* All `String` formatting extensions and functions
* All extensions like `CaptionedInput#toHtmlCaptions`
* All helper extensions for `List<BaseMessageUpdate>`
* Several new extensions for `SentMediaGroupUpdate` were added:
* `SentMediaGroupUpdate#forwardInfo`
* `SentMediaGroupUpdate#replyTo`
* `SentMediaGroupUpdate#chat`
* `SentMediaGroupUpdate#mediaGroupId`
* Several `List<MediaGroupMessage>.createResend` extensions were added
* `RequestsExecutor#executeAsync` and `RequestsExecutor#executeUnsafe`
### 0.27.4
* `TelegramBotAPI-extensions-utils`:
* Several extensions for updates was added:
* `onlyBaseMessageUpdates`
* `onlySentMessageUpdates`
* `onlyEditMessageUpdates`
* `onlyMediaGroupsUpdates`
* `onlySentMediaGroupUpdates`
* `onlyEditMediaGroupUpdates`
* Renames in chat filters extensions:
* `filterBaseMessageUpdates` -> `filterBaseMessageUpdatesByChatId` and `filterBaseMessageUpdatesByChat`
* `filterSentMediaGroupUpdates` -> `filterSentMediaGroupUpdatesByChatId` and `filterSentMediaGroupUpdatesByChat`
### 0.27.3
* `TelegramBotAPI`:

View File

@@ -1,10 +1,15 @@
# TelegramBotAPI
| Common info | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Chat in Telegram](badges/chat.svg)](https://teleg.one/InMoTelegramBotAPI) [![Build Status](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI.svg?branch=master)](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) |
| Common info | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI.svg?branch=master)](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) |
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| TelegramBotAPI status | [![Download](https://api.bintray.com/packages/insanusmokrassar/StandardRepository/TelegramBotAPI/images/download.svg)](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI) |
| Useful links | • [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/) |
| | • [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
| | • [![Chat in Telegram](badges/chat.svg)](https://teleg.one/InMoTelegramBotAPI) |
| | • [![KDocs](badges/kdocs.svg)](https://tgbotapi.inmo.dev/docs/index.html) |
| TelegramBotAPI status | [![Download](https://api.bintray.com/packages/insanusmokrassar/StandardRepository/TelegramBotAPI/images/download.svg)](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI) |
| TelegramBotAPI Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-api/images/download.svg)](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-api/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-api) |
| TelegramBotAPI Util Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-utils/images/download.svg)](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-utils/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-utils) |
| TelegramBotAPI All status | [![Download](https://api.bintray.com/packages/insanusmokrassar/StandardRepository/TelegramBotAPI-all/images/download.svg)](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-all/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-all/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-all) |
It is a complex of libraries for working with `TelegramBotAPI` in type-safe and strict way as much as it possible. In
the list of this complex currently next projects:

View File

@@ -20,37 +20,33 @@ publishing {
publications.all {
artifact javadocsJar
pom.withXml {
asNode().children().last() + {
resolveStrategy = Closure.DELEGATE_FIRST
pom {
description = "This project just include all subproject of TelegramBotAPI"
name = "Telegram Bot API All"
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-all"
description "This project just include all subproject of TelegramBotAPI"
name "Telegram Bot API All"
url "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-all"
scm {
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
scm {
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
developers {
developer {
id = "InsanusMokrassar"
name = "Ovsiannikov Aleksei"
email = "ovsyannikov.alexey95@gmail.com"
}
}
developers {
developer {
id "InsanusMokrassar"
name "Ovsiannikov Aleksei"
email "ovsyannikov.alexey95@gmail.com"
}
}
licenses {
license {
name "Apache Software License 2.0"
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
licenses {
license {
name = "Apache Software License 2.0"
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
}
}

View File

@@ -20,37 +20,33 @@ publishing {
publications.all {
artifact javadocsJar
pom.withXml {
asNode().children().last() + {
resolveStrategy = Closure.DELEGATE_FIRST
pom {
description = "API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference"
name = "Telegram Bot API Extensions for API"
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api"
description "API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference"
name "Telegram Bot API Extensions for API"
url "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api"
scm {
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
scm {
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
developers {
developer {
id = "InsanusMokrassar"
name = "Ovsiannikov Aleksei"
email = "ovsyannikov.alexey95@gmail.com"
}
}
developers {
developer {
id "InsanusMokrassar"
name "Ovsiannikov Aleksei"
email "ovsyannikov.alexey95@gmail.com"
}
}
licenses {
license {
name "Apache Software License 2.0"
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
licenses {
license {
name = "Apache Software License 2.0"
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
}
}

View File

@@ -4,8 +4,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
import com.github.insanusmokrassar.TelegramBotAPI.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.engine.ProxyConfig
import io.ktor.client.engine.*
/**
* @param proxy Standard ktor [ProxyConfig]
@@ -14,20 +13,30 @@ import io.ktor.client.engine.ProxyConfig
*/
data class BotBuilder internal constructor(
var proxy: ProxyConfig? = null,
@Deprecated("ktorClientEngineFactory parameter will be used preferable. In future this parameter will be removed")
var ktorClientEngine: HttpClientEngine? = null,
var ktorClientEngineFactory: HttpClientEngineFactory<out HttpClientEngineConfig>? = null,
var ktorClientConfig: (HttpClientConfig<*>.() -> Unit) ? = null
) {
internal fun createHttpClient(): HttpClient = ktorClientEngine ?.let { engine ->
internal fun createHttpClient(): HttpClient = ktorClientEngineFactory ?.let {
HttpClient(
it.create {
this@create.proxy = this@BotBuilder.proxy ?: this@create.proxy
}
) {
ktorClientConfig ?.let { it() }
}
} ?: ktorClientEngine ?.let { engine ->
HttpClient(engine) {
ktorClientConfig ?.let { it() }
engine {
proxy = this@BotBuilder.proxy ?: proxy
this@engine.proxy = this@BotBuilder.proxy ?: this@engine.proxy
}
}
} ?: HttpClient {
ktorClientConfig ?.let { it() }
engine {
proxy = this@BotBuilder.proxy ?: proxy
this@engine.proxy = this@BotBuilder.proxy ?: this@engine.proxy
}
}
}

View File

@@ -7,3 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.BotCommand
suspend fun RequestsExecutor.setMyCommands(
commands: List<BotCommand>
) = execute(SetMyCommands(commands))
suspend fun RequestsExecutor.setMyCommands(
vararg commands: BotCommand
) = setMyCommands(commands.toList())

View File

@@ -2,8 +2,12 @@ package com.github.insanusmokrassar.TelegramBotAPI.extensions.api.chat.get
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
import com.github.insanusmokrassar.TelegramBotAPI.requests.chat.get.GetChat
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.*
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.*
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.extended.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.PreviewFeature
suspend fun RequestsExecutor.getChat(
chatId: ChatIdentifier
@@ -12,3 +16,117 @@ suspend fun RequestsExecutor.getChat(
suspend fun RequestsExecutor.getChat(
chat: Chat
) = getChat(chat.id)
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedPublicChat] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: PublicChat
) = getChat(chat.id) as ExtendedPublicChat
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedChannelChat] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: ChannelChat
) = getChat(chat.id) as ExtendedChannelChat
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedChannelChatImpl] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: ChannelChatImpl
) = getChat(chat.id) as ExtendedChannelChatImpl
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedGroupChat] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: GroupChat
) = getChat(chat.id) as ExtendedGroupChat
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedGroupChatImpl] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: GroupChatImpl
) = getChat(chat.id) as ExtendedGroupChatImpl
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedSupergroupChat] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: SupergroupChat
) = getChat(chat.id) as ExtendedSupergroupChat
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedSupergroupChatImpl] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: SupergroupChatImpl
) = getChat(chat.id) as ExtendedSupergroupChatImpl
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedPrivateChat] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: PrivateChat
) = getChat(chat.id) as ExtendedPrivateChat
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedPrivateChatImpl] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: PrivateChatImpl
) = getChat(chat.id) as ExtendedPrivateChatImpl
/**
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
* [ExtendedUser] with unsafe operator "as"
*
* @throws ClassCastException
*/
@PreviewFeature
suspend fun RequestsExecutor.getChat(
chat: CommonUser
) = getChat(chat.id) as ExtendedUser

View File

@@ -166,6 +166,32 @@ application without creating of new one server (as it is happening in `startList
There are several filters for flows.
#### Updates
In the next table it is supposed that you are using some `Flow` with type from `Base type of update` and apply
extension `Extension` and will get `Flow` with type from `Result type of update` column.
| Base type of update | Extension | Result type of update |
| ------------------- | --------- | --------------------- |
| `Update` | `onlyBaseMessageUpdates` | `BaseMessageUpdate` |
| | | |
| `BaseMessageUpdate` | `onlySentMessageUpdates` | `BaseSentMessageUpdate` |
| `BaseMessageUpdate` | `onlyEditMessageUpdates` | `BaseEditMessageUpdate` |
| `BaseMessageUpdate` | `onlyMediaGroupsUpdates` | `MediaGroupUpdate` |
| | | |
| `MediaGroupUpdate` | `onlySentMediaGroupUpdates` | `SentMediaGroupUpdate` |
| `MediaGroupUpdate` | `onlyEditMediaGroupUpdates` | `EditMediaGroupUpdate` |
All of these extensions was made for more simple work with the others:
```kotlin
val flow: Flow<BaseMessageUpdate> = ...; // here we are getting flow from somewhere,
// for example, FlowsUpdatesFilter#messageFlow
flow.onlySentMessageUpdates().filterExactCommands(Regex("start"))
```
Here we have used filter `filterExactCommands` which will pass only `ContentMessage` with only one command `start`
#### Sent messages
All sent messages can be filtered for three types:

View File

@@ -20,37 +20,33 @@ publishing {
publications.all {
artifact javadocsJar
pom.withXml {
asNode().children().last() + {
resolveStrategy = Closure.DELEGATE_FIRST
pom {
description = "Util extensions for more useful work with updates and other things"
name = "Telegram Bot API Utility Extensions"
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-utils"
description "Util extensions for more useful work with updates and other things"
name "Telegram Bot API Utility Extensions"
url "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-utils"
scm {
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
scm {
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
developers {
developer {
id = "InsanusMokrassar"
name = "Ovsiannikov Aleksei"
email = "ovsyannikov.alexey95@gmail.com"
}
}
developers {
developer {
id "InsanusMokrassar"
name "Ovsiannikov Aleksei"
email "ovsyannikov.alexey95@gmail.com"
}
}
licenses {
license {
name "Apache Software License 2.0"
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
licenses {
license {
name = "Apache Software License 2.0"
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
}
}

View File

@@ -0,0 +1,34 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.CommonMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
import kotlinx.coroutines.flow.*
/**
* Simple factory to convert [ContentMessage] to a [CommonMessage]
*/
fun <C: MessageContent, T : ContentMessage<C>> Flow<T>.onlyCommonMessages() = filterIsInstance<CommonMessage<C>>()
/**
* Filter the messages and checking that incoming [CommonMessage] is [PossiblySentViaBotCommonMessage] and its
* [PossiblySentViaBotCommonMessage.senderBot] is not null
*/
fun <T : MessageContent> Flow<CommonMessage<T>>.onlySentViaBot() = mapNotNull {
(it as? PossiblySentViaBotCommonMessage) ?.let { possiblySentViaBot ->
if (possiblySentViaBot.senderBot != null) {
possiblySentViaBot
} else {
null
}
}
}
/**
* Filter the messages and checking that incoming [CommonMessage] not is [PossiblySentViaBotCommonMessage] or its
* [PossiblySentViaBotCommonMessage.senderBot] is null
*/
fun <T : MessageContent> Flow<CommonMessage<T>>.withoutSentViaBot() = filter {
it !is PossiblySentViaBotCommonMessage || it.senderBot == null
}

View File

@@ -0,0 +1,16 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
import kotlinx.coroutines.CoroutineScope
/**
* Shortcut for [handleSafely]. It was created for more comfortable way of handling different things
*/
@PreviewFeature
suspend inline fun <T> safely(
noinline onException: ExceptionHandler<T> = { throw it },
noinline block: suspend CoroutineScope.() -> T
): T = handleSafely(
onException,
block
)

View File

@@ -0,0 +1,80 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.formatting
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
import com.github.insanusmokrassar.TelegramBotAPI.types.StickerSetName
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.PrivateChat
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.UsernameChat
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat
import com.github.insanusmokrassar.TelegramBotAPI.utils.link
private const val internalLinkBeginning = "https://t.me"
fun makeLinkToMessage(
username: String,
messageId: MessageIdentifier
): String = "$internalLinkBeginning/$username/$messageId"
private val linkIdRedundantPartRegex = Regex("^-100")
private val usernameBeginSymbolRegex = Regex("^@")
fun makeLinkToMessage(
chat: ExtendedChat,
messageId: MessageIdentifier
): String? {
return when {
chat is UsernameChat && chat.username != null -> {
"$internalLinkBeginning/${chat.username ?.username ?.replace(
usernameBeginSymbolRegex, "")}/$messageId"
}
chat !is PrivateChat -> chat.id.chatId.toString().replace(
linkIdRedundantPartRegex,
""
).let { bareId ->
"$internalLinkBeginning/c/$bareId/$messageId"
}
else -> return null
}
}
private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addstickers"
/**
* Create a link for adding of sticker set with name [stickerSetName]. Was added thanks to user Djaler and based on
* https://github.com/Djaler/evil-bot/blob/master/src/main/kotlin/com/github/djaler/evilbot/utils/StickerUtils.kt#L6-L8
*
* @see [makeLinkToAddStickerSetInMarkdownV2]
* @see [makeLinkToAddStickerSetInMarkdown]
* @see [makeLinkToAddStickerSetInHtml]
*/
fun makeLinkToAddStickerSet(
stickerSetName: StickerSetName,
parseMode: ParseMode
) = (stickerSetName to "$stickerSetAddingLinkPrefix/$stickerSetName").link(
parseMode
)
/**
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [MarkdownV2]
*/
fun makeLinkToAddStickerSetInMarkdownV2(stickerSetName: StickerSetName) =
makeLinkToAddStickerSet(
stickerSetName,
MarkdownV2
)
/**
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [Markdown]
*/
fun makeLinkToAddStickerSetInMarkdown(stickerSetName: StickerSetName) =
makeLinkToAddStickerSet(
stickerSetName,
Markdown
)
/**
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [HTML]
*/
fun makeLinkToAddStickerSetInHtml(stickerSetName: StickerSetName) =
makeLinkToAddStickerSet(
stickerSetName,
HTML
)

View File

@@ -0,0 +1,121 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.formatting
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.fullEntitiesList
fun createFormattedText(
entities: FullTextSourcesList,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
): List<String> {
val texts = mutableListOf<String>()
val textBuilder = StringBuilder(partLength)
for (entity in entities) {
val string = when (mode) {
is MarkdownParseMode -> entity.asMarkdownSource
is MarkdownV2ParseMode -> entity.asMarkdownV2Source
is HTMLParseMode -> entity.asHtmlSource
}
if (textBuilder.length + string.length > partLength) {
if (textBuilder.isNotEmpty()) {
texts.add(textBuilder.toString())
textBuilder.clear()
}
val chunked = string.chunked(partLength)
val last = chunked.last()
textBuilder.append(last)
val listToAdd = if (chunked.size > 1) {
chunked.subList(0, chunked.size - 1)
} else {
emptyList()
}
listToAdd.forEach {
texts.add(it)
}
} else {
textBuilder.append(string)
}
}
if (textBuilder.isNotEmpty()) {
texts.add(textBuilder.toString())
textBuilder.clear()
}
return texts
}
fun createMarkdownText(
entities: FullTextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
fun FullTextSourcesList.toMarkdownCaptions(): List<String> = createMarkdownText(
this,
captionLength.last
)
fun CaptionedInput.toMarkdownCaptions(): List<String> = fullEntitiesList().toMarkdownCaptions()
fun FullTextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
this,
textLength.last
)
fun TextContent.toMarkdownTexts(): List<String> = fullEntitiesList().toMarkdownTexts()
fun FullTextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
this,
explanationLimit.last
)
fun ExplainedInput.toMarkdownExplanations(): List<String> = fullEntitiesList().toMarkdownTexts()
fun createMarkdownV2Text(
entities: FullTextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
fun FullTextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
captionLength.last
)
fun CaptionedInput.toMarkdownV2Captions(): List<String> = fullEntitiesList().toMarkdownV2Captions()
fun FullTextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
this,
textLength.last
)
fun TextContent.toMarkdownV2Texts(): List<String> = fullEntitiesList().toMarkdownV2Texts()
fun FullTextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
this,
explanationLimit.last
)
fun ExplainedInput.toMarkdownV2Explanations(): List<String> = fullEntitiesList().toMarkdownV2Texts()
fun createHtmlText(
entities: FullTextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
fun FullTextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,
captionLength.last
)
fun CaptionedInput.toHtmlCaptions(): List<String> = fullEntitiesList().toHtmlCaptions()
fun FullTextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
this,
textLength.last
)
fun TextContent.toHtmlTexts(): List<String> = fullEntitiesList().toHtmlTexts()
fun FullTextSourcesList.toHtmlExplanations(): List<String> = createHtmlText(
this,
explanationLimit.last
)
fun ExplainedInput.toHtmlExplanations(): List<String> = fullEntitiesList().toHtmlTexts()

View File

@@ -0,0 +1,243 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.formatting
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.*
const val markdownBoldControl = "*"
const val markdownItalicControl = "_"
const val markdownCodeControl = "`"
const val markdownPreControl = "```"
const val markdownV2ItalicUnderlineDelimiter = "\u0013"
const val markdownV2StrikethroughControl = "~"
const val markdownV2UnderlineControl = "__"
const val markdownV2UnderlineEndControl = "$markdownV2UnderlineControl$markdownV2ItalicUnderlineDelimiter"
const val markdownV2ItalicEndControl = "$markdownItalicControl$markdownV2ItalicUnderlineDelimiter"
const val htmlBoldControl = "b"
const val htmlItalicControl = "i"
const val htmlCodeControl = "code"
const val htmlPreControl = "pre"
const val htmlUnderlineControl = "u"
const val htmlStrikethroughControl = "s"
private fun String.markdownDefault(
openControlSymbol: String,
closeControlSymbol: String = openControlSymbol
) = "$openControlSymbol${toMarkdown()}$closeControlSymbol"
private fun String.markdownV2Default(
openControlSymbol: String,
closeControlSymbol: String = openControlSymbol,
escapeFun: String.() -> String = String::escapeMarkdownV2Common
) = "$openControlSymbol${escapeFun()}$closeControlSymbol"
private fun String.htmlDefault(
openControlSymbol: String,
closeControlSymbol: String = openControlSymbol
) = "<$openControlSymbol>${toHtml()}</$closeControlSymbol>"
fun String.linkMarkdown(link: String): String = "[${toMarkdown()}](${link.toMarkdown()})"
fun String.linkMarkdownV2(link: String): String = "[${escapeMarkdownV2Common()}](${link.escapeMarkdownV2Link()})"
fun String.linkHTML(link: String): String = "<a href=\"$link\">${toHtml()}</a>"
fun String.boldMarkdown(): String = markdownDefault(markdownBoldControl)
fun String.boldMarkdownV2(): String = markdownV2Default(markdownBoldControl)
fun String.boldHTML(): String = htmlDefault(htmlBoldControl)
fun String.italicMarkdown(): String = markdownDefault(markdownItalicControl)
fun String.italicMarkdownV2(): String = markdownV2Default(markdownItalicControl, markdownV2ItalicEndControl)
fun String.italicHTML(): String = htmlDefault(htmlItalicControl)
/**
* Crutch for support of strikethrough in default markdown. Simply add modifier, but it will not look like correct
*/
fun String.strikethroughMarkdown(): String = map { it + "\u0336" }.joinToString("")
fun String.strikethroughMarkdownV2(): String = markdownV2Default(markdownV2StrikethroughControl)
fun String.strikethroughHTML(): String = htmlDefault(htmlStrikethroughControl)
/**
* Crutch for support of underline in default markdown. Simply add modifier, but it will not look like correct
*/
fun String.underlineMarkdown(): String = map { it + "\u0347" }.joinToString("")
fun String.underlineMarkdownV2(): String = markdownV2Default(markdownV2UnderlineControl, markdownV2UnderlineEndControl)
fun String.underlineHTML(): String = htmlDefault(htmlUnderlineControl)
fun String.codeMarkdown(): String = markdownDefault(markdownCodeControl)
fun String.codeMarkdownV2(): String = markdownV2Default(markdownCodeControl, escapeFun = String::escapeMarkdownV2PreAndCode)
fun String.codeHTML(): String = htmlDefault(htmlCodeControl)
fun String.preMarkdown(language: String? = null): String = markdownDefault(
"$markdownPreControl${language ?: ""}\n",
"\n$markdownPreControl"
)
fun String.preMarkdownV2(language: String? = null): String = markdownV2Default(
"$markdownPreControl${language ?: ""}\n",
"\n$markdownPreControl",
String::escapeMarkdownV2PreAndCode
)
fun String.preHTML(language: String? = null): String = htmlDefault(
language ?.let {
"$htmlPreControl><$htmlCodeControl class=\"language-$language\""
} ?: htmlPreControl,
language ?.let {
"$htmlCodeControl></$htmlPreControl"
} ?: htmlPreControl
)
fun String.emailMarkdown(): String = linkMarkdown("mailto://$${toMarkdown()}")
fun String.emailMarkdownV2(): String = linkMarkdownV2("mailto://$${toMarkdown()}")
fun String.emailHTML(): String = linkHTML("mailto://$${toHtml()}")
private inline fun String.mention(adapt: String.() -> String): String = if (startsWith("@")) {
adapt()
} else {
"@${adapt()}"
}
private inline fun String.hashTag(adapt: String.() -> String): String = if (startsWith("#")) {
adapt()
} else {
"#${adapt()}"
}
fun String.textMentionMarkdown(userId: UserId): String = linkMarkdown(userId.link)
fun String.textMentionMarkdownV2(userId: UserId): String = linkMarkdownV2(userId.link)
fun String.textMentionHTML(userId: UserId): String = linkHTML(userId.link)
fun String.mentionMarkdown(): String = mention(String::toMarkdown)
fun String.mentionMarkdownV2(): String = mention(String::escapeMarkdownV2Common)
fun String.mentionHTML(): String = mention(String::toHtml)
fun String.hashTagMarkdown(): String = hashTag(String::toMarkdown)
fun String.hashTagMarkdownV2(): String = hashTag(String::escapeMarkdownV2Common).escapeMarkdownV2Common()
fun String.hashTagHTML(): String = hashTag(String::toHtml)
fun String.phoneMarkdown(): String = toMarkdown()
fun String.phoneMarkdownV2(): String = escapeMarkdownV2Common()
fun String.phoneHTML(): String = toHtml()
fun String.command(adapt: String.() -> String): String = if (startsWith("/")) {
adapt()
} else {
"/${adapt()}"
}
fun String.commandMarkdown(): String = command(String::toMarkdown)
fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
fun String.commandHTML(): String = command(String::toHtml)
fun String.regularMarkdown(): String = toMarkdown()
fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
fun String.regularHtml(): String = toHtml()
fun String.cashTagMarkdown(): String = toMarkdown()
fun String.cashTagMarkdownV2(): String = escapeMarkdownV2Common()
fun String.cashTagHtml(): String = toHtml()
infix fun String.bold(parseMode: ParseMode): String = when (parseMode) {
is HTML -> boldHTML()
is Markdown -> boldMarkdown()
is MarkdownV2 -> boldMarkdownV2()
}
infix fun String.italic(parseMode: ParseMode): String = when (parseMode) {
is HTML -> italicHTML()
is Markdown -> italicMarkdown()
is MarkdownV2 -> italicMarkdownV2()
}
infix fun String.hashTag(parseMode: ParseMode): String = when (parseMode) {
is HTML -> hashTagHTML()
is Markdown -> hashTagMarkdown()
is MarkdownV2 -> hashTagMarkdownV2()
}
infix fun String.code(parseMode: ParseMode): String = when (parseMode) {
is HTML -> codeHTML()
is Markdown -> codeMarkdown()
is MarkdownV2 -> codeMarkdownV2()
}
fun String.pre(parseMode: ParseMode, language: String? = null): String = when (parseMode) {
is HTML -> preHTML(language)
is Markdown -> preMarkdown(language)
is MarkdownV2 -> preMarkdownV2(language)
}
infix fun String.pre(parseMode: ParseMode): String = pre(parseMode, null)
infix fun String.email(parseMode: ParseMode): String = when (parseMode) {
is HTML -> emailHTML()
is Markdown -> emailMarkdown()
is MarkdownV2 -> emailMarkdownV2()
}
infix fun Pair<String, String>.link(parseMode: ParseMode): String = when (parseMode) {
is HTML -> first.linkHTML(second)
is Markdown -> first.linkMarkdown(second)
is MarkdownV2 -> first.linkMarkdownV2(second)
}
infix fun String.mention(parseMode: ParseMode): String = when (parseMode) {
is HTML -> mentionHTML()
is Markdown -> mentionMarkdown()
is MarkdownV2 -> mentionMarkdownV2()
}
infix fun Pair<String, ChatId>.mention(parseMode: ParseMode): String = when (parseMode) {
is HTML -> first.textMentionHTML(second)
is Markdown -> first.textMentionMarkdown(second)
is MarkdownV2 -> first.textMentionMarkdownV2(second)
}
infix fun String.phone(parseMode: ParseMode): String = when (parseMode) {
is HTML -> phoneHTML()
is Markdown -> phoneMarkdown()
is MarkdownV2 -> phoneMarkdownV2()
}
infix fun String.command(parseMode: ParseMode): String = when (parseMode) {
is HTML -> commandHTML()
is Markdown -> commandMarkdown()
is MarkdownV2 -> commandMarkdownV2()
}
infix fun String.underline(parseMode: ParseMode): String = when (parseMode) {
is HTML -> underlineHTML()
is Markdown -> underlineMarkdown()
is MarkdownV2 -> underlineMarkdownV2()
}
infix fun String.strikethrough(parseMode: ParseMode): String = when (parseMode) {
is HTML -> strikethroughHTML()
is Markdown -> strikethroughMarkdown()
is MarkdownV2 -> strikethroughMarkdownV2()
}
infix fun String.regular(parseMode: ParseMode): String = when (parseMode) {
is HTML -> regularHtml()
is Markdown -> regularMarkdown()
is MarkdownV2 -> regularMarkdownV2()
}
infix fun String.cashtag(parseMode: ParseMode): String = when (parseMode) {
is HTML -> cashTagHtml()
is Markdown -> cashTagMarkdown()
is MarkdownV2 -> cashTagMarkdownV2()
}

View File

@@ -0,0 +1,56 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendMediaGroup
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
import com.github.insanusmokrassar.TelegramBotAPI.types.message.ForwardInfo
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.SentMediaGroupUpdate
val List<MediaGroupMessage>.forwardInfo: ForwardInfo?
get() = firstOrNull() ?.forwardInfo
val List<MediaGroupMessage>.replyTo: Message?
get() = firstOrNull() ?.replyTo
val List<MediaGroupMessage>.chat: Chat?
get() = firstOrNull() ?.chat
val List<MediaGroupMessage>.mediaGroupId: MediaGroupIdentifier?
get() = firstOrNull() ?.mediaGroupId
val SentMediaGroupUpdate.forwardInfo: ForwardInfo?
get() = data.first().forwardInfo
val SentMediaGroupUpdate.replyTo: Message?
get() = data.first().replyTo
val SentMediaGroupUpdate.chat: Chat
get() = data.chat!!
val SentMediaGroupUpdate.mediaGroupId: MediaGroupIdentifier
get() = data.mediaGroupId!!
fun List<MediaGroupMessage>.createResend(
chatId: ChatId,
disableNotification: Boolean = false,
replyTo: MessageIdentifier? = null
) = SendMediaGroup(
chatId,
map { it.content.toMediaGroupMemberInputMedia() },
disableNotification,
replyTo
)
fun List<MediaGroupMessage>.createResend(
chat: Chat,
disableNotification: Boolean = false,
replyTo: MessageIdentifier? = null
) = createResend(
chat.id,
disableNotification,
replyTo
)
fun SentMediaGroupUpdate.createResend(
disableNotification: Boolean = false,
replyTo: MessageIdentifier? = null
) = data.createResend(
chat,
disableNotification,
replyTo
)

View File

@@ -0,0 +1,45 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.utils.handleSafely
import kotlinx.coroutines.*
fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>,
scope: CoroutineScope
): Deferred<T> = scope.async {
handleSafely {
execute(request)
}
}
suspend fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>
): Deferred<T> = coroutineScope {
executeAsync(request, this)
}
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
request: Request<T>,
retries: Int = 0,
retriesDelay: Long = 1000L,
onAllFailed: (suspend (exceptions: Array<Exception>) -> Unit)? = null
): T? {
var leftRetries = retries
val exceptions = onAllFailed ?.let { mutableListOf<Exception>() }
do {
return handleSafely(
{
leftRetries--
delay(retriesDelay)
exceptions ?.add(it)
null
}
) {
execute(request)
} ?: continue
} while(leftRetries >= 0)
onAllFailed ?.invoke(exceptions ?.toTypedArray() ?: emptyArray())
return null
}

View File

@@ -0,0 +1,11 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.types.buttons
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardButtons.InlineKeyboardButton
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
fun InlineKeyboardMarkup(
vararg buttons: InlineKeyboardButton
): InlineKeyboardMarkup = InlineKeyboardMarkup(
flatMatrix { buttons.forEach { +it } }
)

View File

@@ -0,0 +1,17 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.types.buttons
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.ReplyKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardButton
import com.github.insanusmokrassar.TelegramBotAPI.utils.flatMatrix
fun ReplyKeyboardMarkup(
vararg buttons: KeyboardButton,
resizeKeyboard: Boolean? = null,
oneTimeKeyboard: Boolean? = null,
selective: Boolean? = null
): ReplyKeyboardMarkup = ReplyKeyboardMarkup(
flatMatrix { buttons.forEach { +it } },
resizeKeyboard,
oneTimeKeyboard,
selective
)

View File

@@ -0,0 +1,49 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.mapNotNull
fun Flow<Update>.onlyBaseMessageUpdates(): Flow<BaseMessageUpdate> = mapNotNull {
it as? BaseMessageUpdate
}
/**
* Converts flow to [Flow] of [BaseSentMessageUpdate]
*/
fun Flow<BaseMessageUpdate>.onlySentMessageUpdates(): Flow<BaseSentMessageUpdate> = mapNotNull {
it as? BaseSentMessageUpdate
}
/**
* Converts flow to [Flow] of [BaseSentMessageUpdate]
*/
fun Flow<BaseMessageUpdate>.onlyEditMessageUpdates(): Flow<BaseEditMessageUpdate> = mapNotNull {
it as? BaseEditMessageUpdate
}
/**
* Converts flow to [Flow] of [MediaGroupUpdate]. Please, remember that it could be either [EditMediaGroupUpdate]
* or [SentMediaGroupUpdate]
*
* @see onlySentMediaGroupUpdates
* @see onlyEditMediaGroupUpdates
*/
fun Flow<BaseMessageUpdate>.onlyMediaGroupsUpdates(): Flow<MediaGroupUpdate> = mapNotNull {
it as? MediaGroupUpdate
}
/**
* Converts flow to [Flow] of [SentMediaGroupUpdate]
*/
fun Flow<MediaGroupUpdate>.onlySentMediaGroupUpdates(): Flow<SentMediaGroupUpdate> = mapNotNull {
it as? SentMediaGroupUpdate
}
/**
* Converts flow to [Flow] of [EditMediaGroupUpdate]
*/
fun Flow<MediaGroupUpdate>.onlyEditMediaGroupUpdates(): Flow<EditMediaGroupUpdate> = mapNotNull {
it as? EditMediaGroupUpdate
}

View File

@@ -12,6 +12,13 @@ fun <T : BaseSentMessageUpdate> Flow<T>.asContentMessagesFlow() = mapNotNull {
it.data as? ContentMessage<*>
}
/**
* Will map incoming [BaseSentMessageUpdate]s to [CommonMessage] from [BaseSentMessageUpdate.data]
*/
fun <T : BaseSentMessageUpdate> Flow<T>.asCommonMessagesFlow() = mapNotNull {
it.data as? CommonMessage<*>
}
/**
* Will map incoming [BaseSentMessageUpdate]s to [ChatEventMessage] from [BaseSentMessageUpdate.data]
*/

View File

@@ -10,22 +10,38 @@ import kotlinx.coroutines.flow.filter
/**
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId]
*/
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chatId: ChatId): Flow<T> = filter {
it.data.chat.id == chatId
}
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdatesByChatId(chatId: ChatId): Flow<T> = filter { it.data.chat.id == chatId }
/**
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId] using [Chat.id] of [chat]
*/
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chat: Chat): Flow<T> = filterBaseMessageUpdates(chat.id)
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdatesByChat(chat: Chat): Flow<T> = filterBaseMessageUpdatesByChatId(chat.id)
/**
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId]
*/
@Deprecated("Renamed", ReplaceWith("filterBaseMessageUpdatesByChatId"))
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chatId: ChatId): Flow<T> = filterBaseMessageUpdatesByChatId(chatId)
/**
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId] using [Chat.id] of [chat]
*/
@Deprecated("Renamed", ReplaceWith("filterBaseMessageUpdatesByChat"))
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chat: Chat): Flow<T> = filterBaseMessageUpdatesByChatId(chat.id)
/**
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId]
*/
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chatId: ChatId): Flow<T> = filter {
it.data.first().chat.id == chatId
}
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdatesByChatId(chatId: ChatId): Flow<T> = filter { it.data.first().chat.id == chatId }
/**
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId] using [Chat.id] of [chat]
*/
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chat: Chat): Flow<T> = filterSentMediaGroupUpdates(chat.id)
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdatesByChat(chat: Chat): Flow<T> = filterSentMediaGroupUpdatesByChatId(chat.id)
/**
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId]
*/
@Deprecated("Renamed", ReplaceWith("filterSentMediaGroupUpdatesByChatId"))
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chatId: ChatId): Flow<T> = filterSentMediaGroupUpdatesByChatId(chatId)
/**
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId] using [Chat.id] of [chat]
*/
@Deprecated("Renamed", ReplaceWith("filterSentMediaGroupUpdatesByChat"))
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chat: Chat): Flow<T> = filterSentMediaGroupUpdatesByChatId(chat.id)

View File

@@ -77,7 +77,6 @@ fun startListenWebhooks(
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
block: UpdateReceiver<Update>
): ApplicationEngine {
lateinit var engine: ApplicationEngine
val env = applicationEngineEnvironment {
module {
@@ -103,10 +102,10 @@ fun startListenWebhooks(
}
}
engine = embeddedServer(engineFactory, env)
engine.start(false)
return engine
return embeddedServer(engineFactory, env).also {
it.start(false)
}
}
private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhooks(
@@ -119,14 +118,10 @@ private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhook
privateKeyConfig: WebhookPrivateKeyConfig? = null,
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
block: UpdateReceiver<Update>
): Job {
): ApplicationEngine {
return try {
execute(setWebhookRequest)
val engine = startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
scope.launch {
engine.environment.parentCoroutineContext[Job] ?.join()
engine.stop(1000, 5000)
}
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
} catch (e: Exception) {
throw e
}
@@ -154,7 +149,7 @@ suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
privateKeyConfig: WebhookPrivateKeyConfig? = null,
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
block: UpdateReceiver<Update>
): Job = internalSetWebhookInfoAndStartListenWebhooks(
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
listenPort,
engineFactory,
setWebhookRequest as Request<Boolean>,
@@ -188,7 +183,7 @@ suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
privateKeyConfig: WebhookPrivateKeyConfig? = null,
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
block: UpdateReceiver<Update>
): Job = internalSetWebhookInfoAndStartListenWebhooks(
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
listenPort,
engineFactory,
setWebhookRequest as Request<Boolean>,

View File

@@ -10,7 +10,7 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
## Compatibility
This version compatible with [24th of April 2020 update of TelegramBotAPI (version 4.8)](https://core.telegram.org/bots/api#april-24-2020).
This version compatible with [4th of June 2020 update of TelegramBotAPI (version 4.9)](https://core.telegram.org/bots/api#june-4-2020).
There is only one exception of implemented functionality - Telegram Passport API, which was presented in
[August 2018 update of TelegramBotAPI](https://core.telegram.org/bots/api-changelog#august-27-2018) update. It will be implemented
as soon as possible.

View File

@@ -83,4 +83,12 @@ kotlin {
}
}
}
targets.all {
compilations.all {
kotlinOptions {
freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi", "-Xopt-in=kotlin.RequiresOptIn"]
}
}
}
}

View File

@@ -20,37 +20,33 @@ publishing {
publications.all {
artifact javadocsJar
pom.withXml {
asNode().children().last() + {
resolveStrategy = Closure.DELEGATE_FIRST
pom {
description = "Library for Object-Oriented and type-safe work with Telegram Bot API"
name = "Telegram Bot API"
url = "https://insanusmokrassar.github.io/TelegramBotAPI"
description "Library for Object-Oriented and type-safe work with Telegram Bot API"
name "Telegram Bot API"
url "https://insanusmokrassar.github.io/TelegramBotAPI"
scm {
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
scm {
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
developers {
developer {
id = "InsanusMokrassar"
name = "Ovsiannikov Aleksei"
email = "ovsyannikov.alexey95@gmail.com"
}
}
developers {
developer {
id "InsanusMokrassar"
name "Ovsiannikov Aleksei"
email "ovsyannikov.alexey95@gmail.com"
}
}
licenses {
license {
name "Apache Software License 2.0"
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
licenses {
license {
name = "Apache Software License 2.0"
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
}
}

View File

@@ -13,8 +13,8 @@ import io.ktor.utils.io.core.Closeable
interface RequestsExecutor : Closeable {
/**
* Unsafe execution of incoming [request]. Can throw almost any exception. So, it is better to use
* something like [com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.executeAsync] or
* [com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.executeUnsafe]
* something like [com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts.executeAsync] or
* [com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts.executeUnsafe]
*
* @throws Exception
*/

View File

@@ -9,6 +9,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
internal val TextContentMessageResultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>
@@ -37,7 +38,7 @@ data class SendTextMessage(
{
init {
if (text.length !in textLength) {
throw IllegalArgumentException("Text must be in $textLength range")
throwRangeError("Text length", textLength, text.length)
}
}

View File

@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.AnimationContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendAnimation(
@@ -93,7 +94,7 @@ data class SendAnimationData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -12,6 +12,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.AudioContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendAudio(
@@ -95,7 +96,7 @@ data class SendAudioData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.DocumentContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendDocument(
@@ -79,7 +80,7 @@ data class SendDocumentData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -8,12 +8,15 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.jsonArray
val membersCountInMediaGroup: IntRange = 2 .. 10
@Deprecated("Replaced and renamed", ReplaceWith("mediaCountInMediaGroup", "com.github.insanusmokrassar.TelegramBotAPI.types.mediaCountInMediaGroup"))
val membersCountInMediaGroup
get() = mediaCountInMediaGroup
fun SendMediaGroup(
chatId: ChatIdentifier,
@@ -21,8 +24,8 @@ fun SendMediaGroup(
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null
): Request<List<MediaGroupMessage>> {
if (media.size !in membersCountInMediaGroup) {
throw IllegalArgumentException("Count of members for media group must be in $membersCountInMediaGroup range")
if (media.size !in mediaCountInMediaGroup) {
throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size)
}
val files: List<MultipartFile> = media.flatMap {

View File

@@ -10,6 +10,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.PhotoContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendPhoto(
@@ -65,7 +66,7 @@ data class SendPhotoData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VideoContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendVideo(
@@ -97,7 +98,7 @@ data class SendVideoData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VideoNoteContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendVideoNote(
@@ -92,7 +93,7 @@ data class SendVideoNoteData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VoiceContent
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.*
fun SendVoice(
@@ -84,7 +85,7 @@ data class SendVoiceData internal constructor(
init {
text ?.let {
if (it.length !in captionLength) {
throw IllegalArgumentException("Caption must be in $captionLength range")
throwRangeError("Caption length", captionLength, it.length)
}
}
}

View File

@@ -1,8 +1,11 @@
package com.github.insanusmokrassar.TelegramBotAPI.types
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
val BotCommandNameRegex = Regex("^[a-z_0-9]{${botCommandLengthLimit.first},${botCommandLengthLimit.last}}$")
@Serializable
data class BotCommand(
@SerialName(botCommandField)
@@ -12,10 +15,13 @@ data class BotCommand(
) {
init {
if (command.length !in botCommandLengthLimit) {
error("Command size must be in range $botCommandLengthLimit, but actually have length ${command.length}")
throwRangeError("Command name size", botCommandLengthLimit, command.length)
}
if (!command.matches(BotCommandNameRegex)) {
error("Bot command must contains only lowercase English letters, digits and underscores, but incoming command was $command")
}
if (description.length !in botCommandDescriptionLimit) {
error("Command description size must be in range $botCommandDescriptionLimit, but actually have length ${description.length}")
throwRangeError("Command description size", botCommandDescriptionLimit, description.length)
}
}
}

View File

@@ -1,5 +1,7 @@
package com.github.insanusmokrassar.TelegramBotAPI.types
import com.github.insanusmokrassar.TelegramBotAPI.utils.BuiltinMimeTypes
typealias Identifier = Long
typealias MessageIdentifier = Long
typealias InlineQueryIdentifier = String
@@ -26,8 +28,8 @@ typealias LongSeconds = Long
val getUpdatesLimit = 1 .. 100
val callbackQueryAnswerLength = 0 until 200
val captionLength = 0 until 1024
val textLength = 0 until 4096
val captionLength = 0 .. 1024
val textLength = 1 .. 4096
val userProfilePhotosRequestLimit = 0 .. 100
val chatTitleLength = 1 until 255
val chatDescriptionLength = 0 until 256
@@ -55,12 +57,20 @@ val botCommandLimit = botCommandLengthLimit
val botCommandDescriptionLimit = 3 .. 256
val botCommandsLimit = 0 .. 100
val mediaCountInMediaGroup: IntRange = 2 .. 10
val explanationLimit = 0 .. 200
@Deprecated("Will be removed in near updates", ReplaceWith("explanationLimit"))
val quizPollExplanationLimit = explanationLimit
val openPeriodPollSecondsLimit = 5 .. 600
val telegramInlineModeGifPermittedMimeTypes = listOf(
BuiltinMimeTypes.Image.Jpg,
BuiltinMimeTypes.Image.Gif,
BuiltinMimeTypes.Video.MP4
)
const val chatIdField = "chat_id"
const val messageIdField = "message_id"
const val updateIdField = "update_id"
@@ -175,6 +185,7 @@ const val stickerFileIdField = "sticker_file_id"
const val gameShortNameField = "game_short_name"
const val thumbUrlField = "thumb_url"
const val thumbMimeTypeField = "thumb_mime_type"
const val thumbWidthField = "thumb_width"
const val thumbHeightField = "thumb_height"

View File

@@ -7,6 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.abstracts.
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -18,6 +19,8 @@ data class InlineQueryResultGifImpl(
override val url: String,
@SerialName(thumbUrlField)
override val thumbUrl: String,
@SerialName(thumbMimeTypeField)
override val thumbMimeType: MimeType? = null,
@SerialName(gifWidthField)
override val width: Int? = null,
@SerialName(gifHeightField)
@@ -36,4 +39,10 @@ data class InlineQueryResultGifImpl(
override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultGif {
override val type: String = inlineQueryResultGifType
init {
if (thumbMimeType != null && thumbMimeType !in telegramInlineModeGifPermittedMimeTypes) {
error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes")
}
}
}

View File

@@ -7,6 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.abstracts.
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -18,6 +19,8 @@ data class InlineQueryResultMpeg4GifImpl(
override val url: String,
@SerialName(thumbUrlField)
override val thumbUrl: String,
@SerialName(thumbMimeTypeField)
override val thumbMimeType: MimeType? = null,
@SerialName(mpeg4GifWidthField)
override val width: Int? = null,
@SerialName(mpeg4GifHeightField)
@@ -36,4 +39,10 @@ data class InlineQueryResultMpeg4GifImpl(
override val inputMessageContent: InputMessageContent? = null
) : InlineQueryResultMpeg4Gif {
override val type: String = inlineQueryResultMpeg4GifType
init {
if (thumbMimeType != null && thumbMimeType !in telegramInlineModeGifPermittedMimeTypes) {
error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes")
}
}
}

View File

@@ -1,5 +1,11 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
interface ThumbedInlineQueryResult : InlineQueryResult {
val thumbUrl: String?
}
interface ThumbedWithMimeTypeInlineQueryResult : ThumbedInlineQueryResult {
val thumbMimeType: MimeType?
}

View File

@@ -2,4 +2,4 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQue
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.*
interface InlineQueryResultGif : InlineQueryResultGifCommon, UrlInlineQueryResult, ThumbedInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery
interface InlineQueryResultGif : InlineQueryResultGifCommon, UrlInlineQueryResult, ThumbedWithMimeTypeInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery

View File

@@ -2,4 +2,4 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQue
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.*
interface InlineQueryResultMpeg4Gif : InlineQueryResultMpeg4GifCommon, UrlInlineQueryResult, ThumbedInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery
interface InlineQueryResultMpeg4Gif : InlineQueryResultMpeg4GifCommon, UrlInlineQueryResult, ThumbedWithMimeTypeInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery

View File

@@ -1,12 +1,11 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.message
import com.github.insanusmokrassar.TelegramBotAPI.types.AuthorSignature
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.CommonMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
import com.soywiz.klock.DateTime
data class ChannelMessage<T: MessageContent>(
@@ -18,5 +17,6 @@ data class ChannelMessage<T: MessageContent>(
override val forwardInfo: ForwardInfo?,
override val replyTo: Message?,
override val replyMarkup: InlineKeyboardMarkup?,
override val senderBot: CommonBot?,
val authorSignature: AuthorSignature?
) : CommonMessage<T>
) : PossiblySentViaBotCommonMessage<T>

View File

@@ -1,11 +1,11 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.message
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.User
import com.github.insanusmokrassar.TelegramBotAPI.types.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.payments.SuccessfulPaymentInfo
import com.soywiz.klock.DateTime
@@ -19,5 +19,6 @@ data class CommonMessageImpl<T: MessageContent>(
override val forwardInfo: ForwardInfo?,
override val replyTo: Message?,
override val replyMarkup: InlineKeyboardMarkup?,
override val senderBot: CommonBot?,
val paymentInfo: SuccessfulPaymentInfo?
) : Message, CommonMessage<T>, FromUserMessage
) : PossiblySentViaBotCommonMessage<T>, FromUserMessage

View File

@@ -42,6 +42,7 @@ internal data class RawMessage(
private val forward_sender_name: ForwardSenderName? = null,
private val forward_date: TelegramDate? = null,
private val reply_to_message: RawMessage? = null,
private val via_bot: CommonBot? = null,
private val edit_date: TelegramDate? = null,
private val media_group_id: MediaGroupIdentifier? = null,
private val author_signature: AuthorSignature? = null,
@@ -147,7 +148,7 @@ internal data class RawMessage(
)
forward_from_chat is ChannelChat -> ForwardFromChannelInfo(
forward_date,
forward_from_message_id ?: throw IllegalStateException("Channel forwarded message must contain message id, but was not"),
forward_from_message_id ?: error("Channel forwarded message must contain message id, but was not"),
forward_from_chat,
forward_signature
)
@@ -208,7 +209,7 @@ internal data class RawMessage(
chatEvent as? ChannelEvent ?: throwWrongChatEvent(ChannelEvent::class, chatEvent),
date.asDate
)
else -> throw IllegalStateException("Expected one of the public chats, but was $chat (in extracting of chat event message)")
else -> error("Expected one of the public chats, but was $chat (in extracting of chat event message)")
}
} ?: content?.let { content ->
media_group_id?.let {
@@ -221,7 +222,7 @@ internal data class RawMessage(
when (content) {
is PhotoContent -> content
is VideoContent -> content
else -> throw IllegalStateException("Unsupported content for media group")
else -> error("Unsupported content for media group")
},
edit_date?.asDate,
forwarded,
@@ -237,7 +238,7 @@ internal data class RawMessage(
when (content) {
is PhotoContent -> content
is VideoContent -> content
else -> throw IllegalStateException("Unsupported content for media group")
else -> error("Unsupported content for media group")
},
edit_date?.asDate,
forwarded,
@@ -255,12 +256,12 @@ internal data class RawMessage(
forwarded,
reply_to_message?.asMessage,
reply_markup,
via_bot,
author_signature
)
else -> CommonMessageImpl(
messageId,
from
?: throw IllegalStateException("Was detected common message, but owner (sender) of the message was not found"),
from ?: error("Was detected common message, but owner (sender) of the message was not found"),
chat,
content,
date.asDate,
@@ -268,10 +269,11 @@ internal data class RawMessage(
forwarded,
reply_to_message?.asMessage,
reply_markup,
via_bot,
paymentInfo
)
}
} ?: throw IllegalStateException("Was not found supported type of data")
} ?: error("Was not found supported type of data")
} catch (e: Exception) {
UnknownMessageType(
messageId,
@@ -283,6 +285,6 @@ internal data class RawMessage(
}
private fun throwWrongChatEvent(expected: KClass<*>, but: ChatEvent): CommonEvent {
throw IllegalStateException("Wrong type of chat event: expected $expected, but was $but")
error("Wrong type of chat event: expected $expected, but was $but")
}
}

View File

@@ -0,0 +1,7 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.types.CommonBot
interface PossiblySentViaBot {
val senderBot: CommonBot?
}

View File

@@ -0,0 +1,6 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.CommonMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.PossiblySentViaBot
interface PossiblySentViaBotCommonMessage<T: MessageContent> : CommonMessage<T>, PossiblySentViaBot

View File

@@ -1,7 +1,7 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
@RequiresOptIn(
"It is possible, that behaviour of this thing will be changed later",
"It is possible, that behaviour of this thing will be changed later or this feature will be removed",
RequiresOptIn.Level.WARNING
)
@Target(

View File

@@ -0,0 +1,11 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
object BuiltinMimeTypes {
object Image {
val Jpg = buildMimeType("image/jpeg")
val Gif = buildMimeType("image/gif")
}
object Video {
val MP4 = buildMimeType("video/mp4")
}
}

View File

@@ -6,9 +6,10 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.fullEntitiesList
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun createFormattedText(
entities: FullTextSourcesList,
partLength: Int = 4096,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
): List<String> {
val texts = mutableListOf<String>()
@@ -47,75 +48,96 @@ fun createFormattedText(
}
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun createMarkdownText(
entities: FullTextSourcesList,
partLength: Int = 4096
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toMarkdownCaptions(): List<String> = createMarkdownText(
this,
captionLength.last + 1
captionLength.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun CaptionedInput.toMarkdownCaptions(): List<String> = fullEntitiesList().toMarkdownCaptions()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
this,
textLength.last + 1
textLength.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun TextContent.toMarkdownTexts(): List<String> = fullEntitiesList().toMarkdownTexts()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
this,
explanationLimit.last + 1
explanationLimit.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun ExplainedInput.toMarkdownExplanations(): List<String> = fullEntitiesList().toMarkdownTexts()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun createMarkdownV2Text(
entities: FullTextSourcesList,
partLength: Int = 4096
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
captionLength.last + 1
captionLength.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun CaptionedInput.toMarkdownV2Captions(): List<String> = fullEntitiesList().toMarkdownV2Captions()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
this,
textLength.last + 1
textLength.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun TextContent.toMarkdownV2Texts(): List<String> = fullEntitiesList().toMarkdownV2Texts()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
this,
explanationLimit.last + 1
explanationLimit.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun ExplainedInput.toMarkdownV2Explanations(): List<String> = fullEntitiesList().toMarkdownV2Texts()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun createHtmlText(
entities: FullTextSourcesList,
partLength: Int = 4096
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,
captionLength.last + 1
captionLength.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun CaptionedInput.toHtmlCaptions(): List<String> = fullEntitiesList().toHtmlCaptions()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
this,
textLength.last + 1
textLength.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun TextContent.toHtmlTexts(): List<String> = fullEntitiesList().toHtmlTexts()
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun FullTextSourcesList.toHtmlExplanations(): List<String> = createHtmlText(
this,
explanationLimit.last + 1
explanationLimit.last
)
@Deprecated("Replaced into TelegramBotAPI-extensions-utils")
fun ExplainedInput.toHtmlExplanations(): List<String> = fullEntitiesList().toHtmlTexts()

View File

@@ -7,6 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.
private const val internalLinkBeginning = "https://t.me"
@Deprecated("Replaced into TelegramBotAPI-extensions-utils project")
fun makeLinkToMessage(
username: String,
messageId: MessageIdentifier
@@ -15,6 +16,7 @@ fun makeLinkToMessage(
private val linkIdRedundantPartRegex = Regex("^-100")
private val usernameBeginSymbolRegex = Regex("^@")
@Deprecated("Replaced into TelegramBotAPI-extensions-utils project")
fun makeLinkToMessage(
chat: ExtendedChat,
messageId: MessageIdentifier

View File

@@ -10,16 +10,35 @@ fun <T> MatrixBuilder<T>.row(block: RowBuilder<T>.() -> Unit) {
add(RowBuilder<T>().also(block).row)
}
fun <T> MatrixBuilder<T>.row(vararg elements: T) {
add(elements.toList())
}
fun <T> matrix(block: MatrixBuilder<T>.() -> Unit): Matrix<T> {
return MatrixBuilder<T>().also(block).matrix
}
fun <T> flatMatrix(block: RowBuilder<T>.() -> Unit): Matrix<T> {
return MatrixBuilder<T>().apply {
row(block)
}.matrix
}
fun <T> flatMatrix(vararg elements: T): Matrix<T> {
return MatrixBuilder<T>().apply {
row { elements.forEach { +it } }
}.matrix
}
operator fun <T> RowBuilder<T>.plus(t: T) = add(t)
class RowBuilder<T> {
private val mutRow: MutableList<T> = ArrayList()
val row: List<T>
get() = mutRow
fun add(t: T) = mutRow.add(t)
operator fun T.unaryPlus() = add(this)
}
class MatrixBuilder<T> {

View File

@@ -6,18 +6,22 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.ForwardInfo
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate
@Deprecated("Replaced and updated inside of TelegramBotAPI-extensions-utils")
val List<BaseMessageUpdate>.forwarded: ForwardInfo?
get() = first().let {
(it as? PossiblyForwardedMessage) ?.forwardInfo
}
@Deprecated("Replaced and updated inside of TelegramBotAPI-extensions-utils")
val List<BaseMessageUpdate>.replyTo: Message?
get() = first().let {
(it as? PossiblyReplyMessage) ?.replyTo
}
@Deprecated("Replaced and updated inside of TelegramBotAPI-extensions-utils")
val List<BaseMessageUpdate>.chat: Chat?
get() = first().data.chat
@Deprecated("Replaced and updated inside of TelegramBotAPI-extensions-utils")
val List<BaseMessageUpdate>.mediaGroupId: MediaGroupIdentifier?
get() = (first().data as? MediaGroupMessage) ?.mediaGroupId

View File

@@ -7,5 +7,7 @@ expect class MimeType {
val raw: String
}
expect fun buildMimeType(raw: String): MimeType
@Serializer(MimeType::class)
internal expect object MimeTypeSerializer : KSerializer<MimeType>

View File

@@ -36,50 +36,71 @@ private fun String.htmlDefault(
closeControlSymbol: String = openControlSymbol
) = "<$openControlSymbol>${toHtml()}</$closeControlSymbol>"
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.linkMarkdown(link: String): String = "[${toMarkdown()}](${link.toMarkdown()})"
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.linkMarkdownV2(link: String): String = "[${escapeMarkdownV2Common()}](${link.escapeMarkdownV2Link()})"
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.linkHTML(link: String): String = "<a href=\"$link\">${toHtml()}</a>"
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.boldMarkdown(): String = markdownDefault(markdownBoldControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.boldMarkdownV2(): String = markdownV2Default(markdownBoldControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.boldHTML(): String = htmlDefault(htmlBoldControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.italicMarkdown(): String = markdownDefault(markdownItalicControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.italicMarkdownV2(): String = markdownV2Default(markdownItalicControl, markdownV2ItalicEndControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.italicHTML(): String = htmlDefault(htmlItalicControl)
/**
* Crutch for support of strikethrough in default markdown. Simply add modifier, but it will not look like correct
*/
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.strikethroughMarkdown(): String = map { it + "\u0336" }.joinToString("")
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.strikethroughMarkdownV2(): String = markdownV2Default(markdownV2StrikethroughControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.strikethroughHTML(): String = htmlDefault(htmlStrikethroughControl)
/**
* Crutch for support of underline in default markdown. Simply add modifier, but it will not look like correct
*/
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.underlineMarkdown(): String = map { it + "\u0347" }.joinToString("")
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.underlineMarkdownV2(): String = markdownV2Default(markdownV2UnderlineControl, markdownV2UnderlineEndControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.underlineHTML(): String = htmlDefault(htmlUnderlineControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.codeMarkdown(): String = markdownDefault(markdownCodeControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.codeMarkdownV2(): String = markdownV2Default(markdownCodeControl, escapeFun = String::escapeMarkdownV2PreAndCode)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.codeHTML(): String = htmlDefault(htmlCodeControl)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.preMarkdown(language: String? = null): String = markdownDefault(
"$markdownPreControl${language ?: ""}\n",
"\n$markdownPreControl"
)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.preMarkdownV2(language: String? = null): String = markdownV2Default(
"$markdownPreControl${language ?: ""}\n",
"\n$markdownPreControl",
String::escapeMarkdownV2PreAndCode
)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.preHTML(language: String? = null): String = htmlDefault(
language ?.let {
"$htmlPreControl><$htmlCodeControl class=\"language-$language\""
@@ -90,11 +111,15 @@ fun String.preHTML(language: String? = null): String = htmlDefault(
)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.emailMarkdown(): String = linkMarkdown("mailto://$${toMarkdown()}")
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.emailMarkdownV2(): String = linkMarkdownV2("mailto://$${toMarkdown()}")
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.emailHTML(): String = linkHTML("mailto://$${toHtml()}")
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
private inline fun String.mention(adapt: String.() -> String): String = if (startsWith("@")) {
adapt()
} else {
@@ -102,6 +127,7 @@ private inline fun String.mention(adapt: String.() -> String): String = if (star
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
private inline fun String.hashTag(adapt: String.() -> String): String = if (startsWith("#")) {
adapt()
} else {
@@ -109,47 +135,70 @@ private inline fun String.hashTag(adapt: String.() -> String): String = if (star
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.textMentionMarkdown(userId: UserId): String = linkMarkdown(userId.link)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.textMentionMarkdownV2(userId: UserId): String = linkMarkdownV2(userId.link)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.textMentionHTML(userId: UserId): String = linkHTML(userId.link)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.mentionMarkdown(): String = mention(String::toMarkdown)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.mentionMarkdownV2(): String = mention(String::escapeMarkdownV2Common)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.mentionHTML(): String = mention(String::toHtml)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.hashTagMarkdown(): String = hashTag(String::toMarkdown)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.hashTagMarkdownV2(): String = hashTag(String::escapeMarkdownV2Common).escapeMarkdownV2Common()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.hashTagHTML(): String = hashTag(String::toHtml)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.phoneMarkdown(): String = toMarkdown()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.phoneMarkdownV2(): String = escapeMarkdownV2Common()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.phoneHTML(): String = toHtml()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.command(adapt: String.() -> String): String = if (startsWith("/")) {
adapt()
} else {
"/${adapt()}"
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.commandMarkdown(): String = command(String::toMarkdown)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.commandHTML(): String = command(String::toHtml)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.regularMarkdown(): String = toMarkdown()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.regularHtml(): String = toHtml()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.cashTagMarkdown(): String = toMarkdown()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.cashTagMarkdownV2(): String = escapeMarkdownV2Common()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.cashTagHtml(): String = toHtml()
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.bold(parseMode: ParseMode): String = when (parseMode) {
is HTML -> boldHTML()
is Markdown -> boldMarkdown()
@@ -157,85 +206,100 @@ infix fun String.bold(parseMode: ParseMode): String = when (parseMode) {
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.italic(parseMode: ParseMode): String = when (parseMode) {
is HTML -> italicHTML()
is Markdown -> italicMarkdown()
is MarkdownV2 -> italicMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.hashTag(parseMode: ParseMode): String = when (parseMode) {
is HTML -> hashTagHTML()
is Markdown -> hashTagMarkdown()
is MarkdownV2 -> hashTagMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.code(parseMode: ParseMode): String = when (parseMode) {
is HTML -> codeHTML()
is Markdown -> codeMarkdown()
is MarkdownV2 -> codeMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
fun String.pre(parseMode: ParseMode, language: String? = null): String = when (parseMode) {
is HTML -> preHTML(language)
is Markdown -> preMarkdown(language)
is MarkdownV2 -> preMarkdownV2(language)
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.pre(parseMode: ParseMode): String = pre(parseMode, null)
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.email(parseMode: ParseMode): String = when (parseMode) {
is HTML -> emailHTML()
is Markdown -> emailMarkdown()
is MarkdownV2 -> emailMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun Pair<String, String>.link(parseMode: ParseMode): String = when (parseMode) {
is HTML -> first.linkHTML(second)
is Markdown -> first.linkMarkdown(second)
is MarkdownV2 -> first.linkMarkdownV2(second)
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.mention(parseMode: ParseMode): String = when (parseMode) {
is HTML -> mentionHTML()
is Markdown -> mentionMarkdown()
is MarkdownV2 -> mentionMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun Pair<String, ChatId>.mention(parseMode: ParseMode): String = when (parseMode) {
is HTML -> first.textMentionHTML(second)
is Markdown -> first.textMentionMarkdown(second)
is MarkdownV2 -> first.textMentionMarkdownV2(second)
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.phone(parseMode: ParseMode): String = when (parseMode) {
is HTML -> phoneHTML()
is Markdown -> phoneMarkdown()
is MarkdownV2 -> phoneMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.command(parseMode: ParseMode): String = when (parseMode) {
is HTML -> commandHTML()
is Markdown -> commandMarkdown()
is MarkdownV2 -> commandMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.underline(parseMode: ParseMode): String = when (parseMode) {
is HTML -> underlineHTML()
is Markdown -> underlineMarkdown()
is MarkdownV2 -> underlineMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.strikethrough(parseMode: ParseMode): String = when (parseMode) {
is HTML -> strikethroughHTML()
is Markdown -> strikethroughMarkdown()
is MarkdownV2 -> strikethroughMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.regular(parseMode: ParseMode): String = when (parseMode) {
is HTML -> regularHtml()
is Markdown -> regularMarkdown()
is MarkdownV2 -> regularMarkdownV2()
}
@Deprecated("Replaced into project TelegramBotAPI-extensions-utils")
infix fun String.cashtag(parseMode: ParseMode): String = when (parseMode) {
is HTML -> cashTagHtml()
is Markdown -> cashTagMarkdown()

View File

@@ -0,0 +1,7 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
internal fun throwRangeError(
valueName: String,
range: IntRange,
actualValue: Int
): Nothing = error("$valueName must be in range $range, but was $actualValue")

View File

@@ -7,7 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.Response
import com.github.insanusmokrassar.TelegramBotAPI.utils.handleSafely
import kotlinx.coroutines.*
@Deprecated("Will be removed in next major update")
fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>,
onFail: (suspend (Response) -> Unit)? = null,
@@ -24,6 +24,7 @@ fun <T: Any> RequestsExecutor.executeAsync(
}
}
@Deprecated("Replaced and modified inside of TelegramBotAPI-extensions-utils")
fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>,
scope: CoroutineScope = GlobalScope
@@ -31,6 +32,7 @@ fun <T: Any> RequestsExecutor.executeAsync(
return scope.async { execute(request) }
}
@Deprecated("Replaced and modified inside of TelegramBotAPI-extensions-utils")
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
request: Request<T>,
retries: Int = 0,

View File

@@ -23,7 +23,7 @@ internal actual object MimeTypeSerializer : KSerializer<MimeType> {
override fun deserialize(decoder: Decoder): MimeType {
val mimeType = decoder.decodeString()
return mimesCache.getOrPut(mimeType) {
MimeType(mimeType)
buildMimeType(mimeType)
}
}
@@ -31,3 +31,5 @@ internal actual object MimeTypeSerializer : KSerializer<MimeType> {
encoder.encodeString(value.raw)
}
}
actual fun buildMimeType(raw: String) = MimeType(raw)

View File

@@ -24,3 +24,5 @@ internal actual object MimeTypeSerializer : KSerializer<MimeType> {
encoder.encodeString(value.raw)
}
}
actual fun buildMimeType(raw: String): MimeType = MimeType(raw)

View File

@@ -12,9 +12,9 @@
<path fill="url(#b)" d="M0 0h104v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
<text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="250">Talk</text>
<text x="175" y="140" transform="scale(.1)" textLength="250">Talk</text>
<text x="690" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="600">Telegram</text>
<text x="690" y="140" transform="scale(.1)" textLength="600">Telegram</text>
<text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Talk</text>
<text x="175" y="140" transform="scale(.1)">Talk</text>
<text x="690" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Telegram</text>
<text x="690" y="140" transform="scale(.1)">Telegram</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1018 B

20
badges/kdocs.svg Normal file
View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="104" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="a">
<rect width="104" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#a)">
<path fill="#555" d="M0 0h65v20H0z"/>
<path fill="#007ec6" d="M45 0h69v20H45z"/>
<path fill="url(#b)" d="M0 0h104v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
<text x="225" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Open</text>
<text x="225" y="140" transform="scale(.1)">Open</text>
<text x="740" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">KDocs</text>
<text x="740" y="140" transform="scale(.1)">KDocs</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1012 B

View File

@@ -63,11 +63,17 @@ private Closure includeSourcesInDokka(String... approximateNames) {
}
}
String dokkaFolder = "$buildDir/dokka"
dokka {
outputFormat = 'html'
outputDirectory = dokkaFolder
switch (true) {
case project.hasProperty("DOKKA_PATH"):
outputDirectory = project.property("DOKKA_PATH").toString()
break
case System.getenv("DOKKA_PATH") != null:
outputDirectory = System.getenv("DOKKA_PATH")
break
}
multiplatform {
global {

View File

@@ -1,14 +1,14 @@
kotlin.code.style=official
kotlin_version=1.3.72
kotlin_coroutines_version=1.3.6
kotlin_coroutines_version=1.3.7
kotlin_serialisation_runtime_version=0.20.0
klock_version=1.11.1
klock_version=1.11.3
uuid_version=0.1.0
ktor_version=1.3.2
javax_activation_version=1.1.1
library_group=com.github.insanusmokrassar
library_version=0.27.3
library_version=0.27.7
gradle_bintray_plugin_version=1.8.4

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip