1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-12-07 06:45:57 +00:00

Compare commits

..

23 Commits

Author SHA1 Message Date
8804a24013 small refactoring 2020-09-22 18:12:48 +06:00
8b5244d8df hotfix 2020-09-22 18:06:50 +06:00
034901a479 add publication of github release via changelog 2020-09-22 18:04:10 +06:00
7043647584 changelog parser script has been added 2020-09-22 15:15:20 +06:00
acd9505a5d inline queries extensions 2020-09-22 14:47:34 +06:00
46c33d5ec4 update dependencies 2020-09-22 11:33:47 +06:00
89dc7a4b2a InlineQueryResult#id type change 2020-09-20 20:16:14 +06:00
e4f305b3ec start 0.28.3 2020-09-20 20:11:27 +06:00
d56c132201 Reorder 0.28.* changelogs 2020-09-16 19:28:05 +06:00
d336e177dd Merge pull request #135 from InsanusMokrassar/0.28.2
0.28.2
2020-09-16 11:45:22 +06:00
15e29286fb commonMessages and sent via bot shortcuts updates 2020-09-14 00:12:28 +06:00
314ceed78e signature change in filterCommandsWithArgs 2020-09-13 23:58:09 +06:00
3fa3aa50d9 commands shortcuts 2020-09-13 23:42:59 +06:00
571296b9a0 start 0.28.2 2020-09-13 23:32:47 +06:00
3f13e5d062 Merge pull request #132 from InsanusMokrassar/0.28.1
0.28.1
2020-09-12 22:38:24 +06:00
1874023c05 fixes in build + changes in signature of executeUnsafe 2020-09-12 16:22:39 +06:00
dc0fda2066 update handleSafely 2020-09-12 16:18:00 +06:00
c0d4a4f01b update gradle wrapper version 2020-09-12 15:49:09 +06:00
603762bc22 update kotlin and UUID versions 2020-09-12 15:44:44 +06:00
4db82d6ce2 start 0.28.1 2020-09-12 15:40:12 +06:00
9bf8f56254 update SimpleInputFilesTest 2020-08-29 19:52:46 +06:00
9c926a2265 update SimpleInputFilesTest 2020-08-29 19:51:10 +06:00
747854f4f4 Merge pull request #123 from InsanusMokrassar/0.28.0
0.28.0
2020-08-29 18:46:16 +06:00
41 changed files with 365 additions and 76 deletions

3
.gitignore vendored
View File

@@ -8,3 +8,6 @@ settings.xml
.gradle/
build/
out/
local.properties
secret.gradle

View File

@@ -42,6 +42,52 @@
* `HttpClient#loadFile`
* `PathedFile#download`
### 0.28.3
* Common:
* Version updates:
* `Klock`: `0.12.0` -> `0.12.1`
* `Kotlin serialization`: `1.0.0-RC` -> `1.0.0-RC2` (dependency `kotlinx-serialization-core` was replaced with
`kotlinx-serialization-json` due to [kotlinx.serialization library update](https://github.com/Kotlin/kotlinx.serialization/blob/master/CHANGELOG.md#100-rc2--2020-09-21))
* `TelegramBotAPI-core`:
* All `InlineQueryResult` has changed their type of id for more obvious relation between `InlineQueryResult#id` and
`ChosenInlineResult#resultId`: `String` -> `InlineQueryIdentifier`
* `TelegramBotAPI-extensions-utils`:
* Several extensions for updates flows based on `InlineQueryUpdate` has been added:
* `Flow<InlineQueryUpdate>#onlyBaseInlineQueriesWithUpdates`
* `Flow<InlineQueryUpdate>#onlyBaseInlineQueries`
* `Flow<InlineQueryUpdate>#onlyLocationInlineQueriesWithUpdates`
* `Flow<InlineQueryUpdate>#onlyLocationInlineQueries`
* Several extensions for updates flows based on `ChosenInlineResultUpdate` has been added:
* `Flow<ChosenInlineResultUpdate>.onlyBaseChosenInlineResultsWithUpdates`
* `Flow<ChosenInlineResultUpdate>.onlyBaseChosenInlineResults`
* `Flow<ChosenInlineResultUpdate>.onlyLocationChosenInlineResultsWithUpdates`
* `Flow<ChosenInlineResultUpdate>.onlyLocationChosenInlineResults`
### 0.28.2
* `TelegramBotAPI-extensions-utils`:
* Several commands shortcuts for `Flow<ContentMessage<TextContent>>` has been added:
* `filterExactCommands`
* `filterCommandsInsideTextMessages`
* `filterCommandsWithArgs`
* Extension `Flow<BaseSentMessageUpdate>.filterCommandsWithArgs` has changed its signature: now it will also have
original message paired with list of text sources
* Shortcut method `commonMessages` for `onlyCommonMessages`
* Shortcuts `onlySentViaBot` and `withoutSentViaBot` now are extensions for any `Flow` with types which implementing
`ContentMessage`
### 0.28.1
* Common:
* Versions updates:
* `Kotlin`: `1.4.0` -> `1.4.10`
* `UUID`: `0.2.1` -> `0.2.2`
* `TelegramBotAPI-core`:
* `ExceptionHandler` has changed its incoming type: `Exception` -> `Throwable`
* `handleSafely` has changed its signature
* `executeUnsafe` has changed its signature
## 0.27.0
* `Common`:

View File

@@ -41,7 +41,7 @@ kotlin {
dependencies {
implementation kotlin('stdlib')
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlin_serialisation_runtime_version"
api "org.jetbrains.kotlinx:kotlinx-serialization-properties:$kotlin_serialisation_runtime_version"
api "com.soywiz.korlibs.klock:klock:$klock_version"

View File

@@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable
@Serializable
class InlineQueryResultArticle(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(titleField)
override val title: String,
@SerialName(inputMessageContentField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultAudioCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(audioFileIdField)
override val fileId: FileId,
@SerialName(captionField)

View File

@@ -13,7 +13,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultAudioImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(audioUrlField)
override val url: String,
@SerialName(titleField)

View File

@@ -11,7 +11,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultContact(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(phoneNumberField)
override val phoneNumber: String,
@SerialName(firstNameField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultDocumentCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(documentFileIdField)
override val fileId: FileId,
@SerialName(titleField)

View File

@@ -15,7 +15,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultDocumentImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(documentUrlField)
override val url: String,
@SerialName(titleField)

View File

@@ -1,6 +1,7 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueryIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.gameShortNameField
import kotlinx.serialization.SerialName
@@ -8,7 +9,7 @@ import kotlinx.serialization.Serializable
@Serializable
class InlineQueryResultGame(
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(gameShortNameField)
val gameShortName: String,
override val replyMarkup: InlineKeyboardMarkup? = null

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultGifCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(gifFileIdField)
override val fileId: FileId,
@SerialName(titleField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultGifImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(gifUrlField)
override val url: String,
@SerialName(thumbUrlField)

View File

@@ -12,7 +12,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultLocation(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(latitudeField)
override val latitude: Double,
@SerialName(longitudeField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultMpeg4GifCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(mpeg4GifFileIdField)
override val fileId: FileId,
@SerialName(titleField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultMpeg4GifImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(mpeg4GifUrlField)
override val url: String,
@SerialName(thumbUrlField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultPhotoCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(photoFileIdField)
override val fileId: FileId,
@SerialName(titleField)

View File

@@ -13,7 +13,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultPhotoImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(photoUrlField)
override val url: String,
@SerialName(thumbUrlField)

View File

@@ -11,7 +11,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultStickerCached(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(stickerFileIdField)
override val fileId: FileId,
@SerialName(replyMarkupField)

View File

@@ -12,7 +12,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultVenue(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(latitudeField)
override val latitude: Double,
@SerialName(longitudeField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultVideoCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(videoFileIdField)
override val fileId: FileId,
@SerialName(titleField)

View File

@@ -15,7 +15,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultVideoImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(videoUrlField)
override val url: String,
@SerialName(thumbUrlField)

View File

@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultVoiceCachedImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(voiceFileIdField)
override val fileId: FileId,
@SerialName(titleField)

View File

@@ -13,7 +13,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class InlineQueryResultVoiceImpl(
@SerialName(idField)
override val id: String,
override val id: InlineQueryIdentifier,
@SerialName(voiceUrlField)
override val url: String,
@SerialName(titleField)

View File

@@ -1,12 +1,13 @@
package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.serializers.InlineQueryResultSerializer
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueryIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
import kotlinx.serialization.Serializable
@Serializable(InlineQueryResultSerializer::class)
interface InlineQueryResult {
val type: String
val id: String
val id: InlineQueryIdentifier
val replyMarkup: InlineKeyboardMarkup?
}

View File

@@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.supervisorScope
typealias ExceptionHandler<T> = suspend (Exception) -> T
typealias ExceptionHandler<T> = suspend (Throwable) -> T
/**
* It will run [block] inside of [supervisorScope] to avoid problems with catching of exceptions
*
@@ -17,7 +17,7 @@ suspend inline fun <T> handleSafely(
): T {
return try {
supervisorScope(block)
} catch (e: Exception) {
} catch (e: Throwable) {
onException(e)
}
}

View File

@@ -8,6 +8,7 @@ internal val nonstrictJsonFormat = Json {
ignoreUnknownKeys = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
encodeDefaults = true
}
fun <T: Any> T.toJsonWithoutNulls(serializer: SerializationStrategy<T>): JsonObject = toJson(serializer).withoutNulls()

View File

@@ -6,12 +6,14 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.files.PhotoSize
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.PhotoContent
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals
private val nonstrictJsonFormat = Json {
isLenient = true
ignoreUnknownKeys = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
encodeDefaults = true
}
class SimpleInputFilesTest {
@@ -22,9 +24,18 @@ class SimpleInputFilesTest {
PhotoSize("example_file_id".toInputFile(), "example_unique_file_id", 100, 100, 100)
)
)
nonstrictJsonFormat.encodeToString(
val inputMedia = photoContent.toMediaGroupMemberInputMedia()
assertEquals(photoContent.media.fileId, inputMedia.file)
val encoded = nonstrictJsonFormat.encodeToString(
MediaGroupMemberInputMediaSerializer,
photoContent.toMediaGroupMemberInputMedia()
inputMedia
)
assertEquals(
inputMedia,
nonstrictJsonFormat.decodeFromString(
MediaGroupMemberInputMediaSerializer,
encoded
)
)
}
}

View File

@@ -2,4 +2,6 @@ package com.github.insanusmokrassar.TelegramBotAPI
import kotlinx.serialization.json.Json
val TestsJsonFormat = Json {}
val TestsJsonFormat = Json {
encodeDefaults = true
}

View File

@@ -8,4 +8,5 @@ internal val nonstrictJsonFormat = Json {
ignoreUnknownKeys = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
encodeDefaults = true
}

View File

@@ -1,7 +1,6 @@
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.abstracts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
import kotlinx.coroutines.flow.*
@@ -11,17 +10,21 @@ import kotlinx.coroutines.flow.*
*/
fun <C: MessageContent, T : ContentMessage<C>> Flow<T>.onlyCommonMessages() = filterIsInstance<CommonMessage<C>>()
/**
* Shortcut for [onlyCommonMessages]
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <C: MessageContent, T : ContentMessage<C>> Flow<T>.commonMessages() = onlyCommonMessages()
/**
* 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
}
fun <MC : MessageContent, M : ContentMessage<MC>> Flow<M>.onlySentViaBot() = mapNotNull {
if (it is PossiblySentViaBot && it.senderBot != null) {
it
} else {
null
}
}
@@ -29,6 +32,6 @@ fun <T : MessageContent> Flow<CommonMessage<T>>.onlySentViaBot() = mapNotNull {
* 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
fun <MC : MessageContent, M : ContentMessage<MC>> Flow<M>.withoutSentViaBot() = filter {
it !is PossiblySentViaBot || it.senderBot == null
}

View File

@@ -8,4 +8,5 @@ internal val nonstrictJsonFormat = Json {
ignoreUnknownKeys = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
encodeDefaults = true
}

View File

@@ -0,0 +1,16 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.internal_utils
import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.mapNotNull
internal inline fun <reified T : Any, UT : Update> Flow<UT>.onlySpecifiedTypeOfDataWithUpdates(): Flow<Pair<UpdateIdentifier, T>> {
return mapNotNull {
it.updateId to (it.data as? T ?: return@mapNotNull null)
}
}
internal inline fun <reified T : Any, UT : Update> Flow<UT>.onlySpecifiedTypeOfData(): Flow<T> {
return mapNotNull { it as? T }
}

View File

@@ -0,0 +1,94 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextSource
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.onlyTextContentMessages
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.asContentMessagesFlow
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.BotCommandTextSource
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.RegularTextSource
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.fullEntitiesList
import kotlinx.coroutines.flow.*
/**
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
* messages with [fullEntitiesList] and check that incoming message contains ONLY ONE [TextSource] and that is
* [BotCommandTextSource]. Besides, it is checking that [BotCommandTextSource.command] [Regex.matches] with incoming
* [commandRegex]
*
* @return The same message in case if it contains only [BotCommandTextSource] with [Regex.matches]
* [BotCommandTextSource.command]
*
* @see fullEntitiesList
* @see asContentMessagesFlow
* @see onlyTextContentMessages
* @see textMessages
*/
fun <T : ContentMessage<TextContent>> Flow<T>.filterExactCommands(
commandRegex: Regex
) = filter { contentMessage ->
(contentMessage.content.fullEntitiesList().singleOrNull() as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
}
/**
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
* messages with [fullEntitiesList] and check that incoming message contains [BotCommandTextSource]. Besides, it is
* checking that [BotCommandTextSource.command] [Regex.matches] with incoming [commandRegex]
*
* @return The same message in case if it contains somewhere in text [BotCommandTextSource] with [Regex.matches]
* [BotCommandTextSource.command]
*
* @see fullEntitiesList
* @see asContentMessagesFlow
* @see onlyTextContentMessages
* @see textMessages
*/
fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsInsideTextMessages(
commandRegex: Regex
) = filter { contentMessage ->
contentMessage.content.fullEntitiesList().any {
(it as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
}
}
/**
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
* messages with [fullEntitiesList] and check that incoming message contains first [TextSource] as
* [BotCommandTextSource]. Besides, it is checking that [BotCommandTextSource.command] [Regex.matches] with incoming
* [commandRegex] and for other [TextSource] objects used next rules: all incoming text sources will be passed as is,
* [RegularTextSource] will be split by " " for several [RegularTextSource] which will contains not empty args without
* spaces.
*
* @return Paired original message and converted list with first entity [BotCommandTextSource] and than all others
* according to rules in description
*
* @see fullEntitiesList
* @see asContentMessagesFlow
* @see onlyTextContentMessages
* @see textMessages
*/
fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsWithArgs(
commandRegex: Regex
) = mapNotNull { contentMessage ->
val allEntities = contentMessage.content.fullEntitiesList()
(allEntities.firstOrNull() as? BotCommandTextSource) ?.let {
if (commandRegex.matches(it.command)) {
contentMessage to allEntities.flatMap {
when (it) {
is RegularTextSource -> it.source.split(" ").mapNotNull { regularTextSourcePart ->
if (regularTextSourcePart.isNotBlank()) {
RegularTextSource(regularTextSourcePart)
} else {
null
}
}
else -> listOf(it)
}
}
} else {
null
}
}
}

View File

@@ -24,10 +24,10 @@ suspend fun <T: Any> RequestsExecutor.executeUnsafe(
request: Request<T>,
retries: Int = 0,
retriesDelay: Long = 1000L,
onAllFailed: (suspend (exceptions: Array<Exception>) -> Unit)? = null
onAllFailed: (suspend (exceptions: Array<Throwable>) -> Unit)? = null
): T? {
var leftRetries = retries
val exceptions = onAllFailed ?.let { mutableListOf<Exception>() }
val exceptions = onAllFailed ?.let { mutableListOf<Throwable>() }
do {
return handleSafely(
{

View File

@@ -0,0 +1,36 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.internal_utils.onlySpecifiedTypeOfData
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.internal_utils.onlySpecifiedTypeOfDataWithUpdates
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.ChosenInlineResult.BaseChosenInlineResult
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.ChosenInlineResult.LocationChosenInlineResult
import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.update.ChosenInlineResultUpdate
import com.github.insanusmokrassar.TelegramBotAPI.types.update.InlineQueryUpdate
import kotlinx.coroutines.flow.Flow
/**
* @return Mapped [Flow] with [Pair]s. [Pair.first] in this pair will be [UpdateIdentifier]. It could be useful in
* cases you are using [InlineQueryUpdate.updateId] for some reasons. [Pair.second] will always be [BaseChosenInlineResult].
*/
fun Flow<ChosenInlineResultUpdate>.onlyBaseChosenInlineResultsWithUpdates(): Flow<Pair<UpdateIdentifier, BaseChosenInlineResult>> = onlySpecifiedTypeOfDataWithUpdates()
/**
* @return Filter updates only with [BaseChosenInlineResult] and map it to a [Flow] with values [BaseChosenInlineResult]
*
* @see onlyBaseChosenInlineResultsWithUpdates
*/
fun Flow<ChosenInlineResultUpdate>.onlyBaseChosenInlineResults(): Flow<BaseChosenInlineResult> = onlySpecifiedTypeOfData()
/**
* @return Mapped [Flow] with [Pair]s. [Pair.first] in this pair will be [UpdateIdentifier]. It could be useful in
* cases you are using [InlineQueryUpdate.updateId] for some reasons. [Pair.second] will always be [LocationChosenInlineResult].
*/
fun Flow<ChosenInlineResultUpdate>.onlyLocationChosenInlineResultsWithUpdates(): Flow<Pair<UpdateIdentifier, LocationChosenInlineResult>> = onlySpecifiedTypeOfDataWithUpdates()
/**
* @return Filter updates only with [LocationChosenInlineResult] and map it to a [Flow] with values [LocationChosenInlineResult]
*
* @see onlyLocationChosenInlineResultsWithUpdates
*/
fun Flow<ChosenInlineResultUpdate>.onlyLocationChosenInlineResults(): Flow<LocationChosenInlineResult> = onlySpecifiedTypeOfData()

View File

@@ -2,8 +2,11 @@ package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextSource
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.onlyTextContentMessages
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts.*
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.BotCommandTextSource
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.RegularTextSource
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.fullEntitiesList
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseSentMessageUpdate
import kotlinx.coroutines.flow.*
@@ -23,9 +26,7 @@ import kotlinx.coroutines.flow.*
*/
fun <T : BaseSentMessageUpdate> Flow<T>.filterExactCommands(
commandRegex: Regex
) = asContentMessagesFlow().onlyTextContentMessages().filter { contentMessage ->
(contentMessage.content.fullEntitiesList().singleOrNull() as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
}
) = textMessages().filterExactCommands(commandRegex)
/**
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
@@ -41,11 +42,7 @@ fun <T : BaseSentMessageUpdate> Flow<T>.filterExactCommands(
*/
fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsInsideTextMessages(
commandRegex: Regex
) = asContentMessagesFlow().onlyTextContentMessages().filter { contentMessage ->
contentMessage.content.fullEntitiesList().any {
(it as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
}
}
) = textMessages().filterCommandsInsideTextMessages(commandRegex)
/**
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
@@ -55,7 +52,8 @@ fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsInsideTextMessages(
* [RegularTextSource] will be split by " " for several [RegularTextSource] which will contains not empty args without
* spaces.
*
* @return Converted list with first entity [BotCommandTextSource] and than all others according to rules in description
* @return Paired original message and converted list with first entity [BotCommandTextSource] and than all others
* according to rules in description
*
* @see fullEntitiesList
* @see asContentMessagesFlow
@@ -63,24 +61,4 @@ fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsInsideTextMessages(
*/
fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsWithArgs(
commandRegex: Regex
): Flow<List<TextSource>> = asContentMessagesFlow().onlyTextContentMessages().mapNotNull { contentMessage ->
val allEntities = contentMessage.content.fullEntitiesList()
(allEntities.firstOrNull() as? BotCommandTextSource) ?.let {
if (commandRegex.matches(it.command)) {
allEntities.flatMap {
when (it) {
is RegularTextSource -> it.source.split(" ").mapNotNull { regularTextSourcePart ->
if (regularTextSourcePart.isNotBlank()) {
RegularTextSource(regularTextSourcePart)
} else {
null
}
}
else -> listOf(it)
}
}
} else {
null
}
}
}
): Flow<Pair<ContentMessage<TextContent>, List<TextSource>>> = textMessages().filterCommandsWithArgs(commandRegex)

View File

@@ -0,0 +1,35 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.internal_utils.onlySpecifiedTypeOfData
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.internal_utils.onlySpecifiedTypeOfDataWithUpdates
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.query.BaseInlineQuery
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.query.LocationInlineQuery
import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
import com.github.insanusmokrassar.TelegramBotAPI.types.update.InlineQueryUpdate
import kotlinx.coroutines.flow.*
/**
* @return Mapped [Flow] with [Pair]s. [Pair.first] in this pair will be [UpdateIdentifier]. It could be useful in
* cases you are using [InlineQueryUpdate.updateId] for some reasons. [Pair.second] will always be [BaseInlineQuery].
*/
fun Flow<InlineQueryUpdate>.onlyBaseInlineQueriesWithUpdates(): Flow<Pair<UpdateIdentifier, BaseInlineQuery>> = onlySpecifiedTypeOfDataWithUpdates()
/**
* @return Filter updates only with [BaseInlineQuery] and map it to a [Flow] with values [BaseInlineQuery]
*
* @see onlyBaseInlineQueriesWithUpdates
*/
fun Flow<InlineQueryUpdate>.onlyBaseInlineQueries(): Flow<BaseInlineQuery> = onlySpecifiedTypeOfData()
/**
* @return Mapped [Flow] with [Pair]s. [Pair.first] in this pair will be [UpdateIdentifier]. It could be useful in
* cases you are using [InlineQueryUpdate.updateId] for some reasons. [Pair.second] will always be [LocationInlineQuery].
*/
fun Flow<InlineQueryUpdate>.onlyLocationInlineQueriesWithUpdates(): Flow<Pair<UpdateIdentifier, LocationInlineQuery>> = onlySpecifiedTypeOfDataWithUpdates()
/**
* @return Filter updates only with [LocationInlineQuery] and map it to a [Flow] with values [LocationInlineQuery]
*
* @see onlyLocationInlineQueriesWithUpdates
*/
fun Flow<InlineQueryUpdate>.onlyLocationInlineQueries(): Flow<LocationInlineQuery> = onlySpecifiedTypeOfData()

View File

@@ -3,12 +3,14 @@ buildscript {
mavenLocal()
jcenter()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
classpath "com.github.breadmoirai:github-release:$github_release_plugin_version"
}
}
@@ -16,3 +18,31 @@ plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version" apply false
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version" apply false
}
private String getCurrentVersionChangelog() {
OutputStream changelogDataOS = new ByteArrayOutputStream()
exec {
standardOutput = changelogDataOS
commandLine './changelog_info_retriever', "$library_version", 'CHANGELOG.md'
}
return changelogDataOS.toString().trim()
}
if (new File(projectDir, "secret.gradle").exists()) {
apply from: './secret.gradle'
apply plugin: "com.github.breadmoirai.github-release"
githubRelease {
token "${project.property('GITHUB_RELEASE_TOKEN')}"
owner "InsanusMokrassar"
repo "TelegramBotAPI"
tagName "$library_version"
releaseName "$library_version"
targetCommitish "$library_version"
body getCurrentVersionChangelog()
}
}

29
changelog_info_retriever Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
function parse() {
version=$1
read -r
while [ -z "`echo $REPLY | grep -e "^#\+ $version"`" ]
do
read -r
done
read -r
while [ -z "`echo $REPLY | grep -e "^#\+"`" ]
do
echo "$REPLY"
read -r
done
}
version=$1
file=$2
if [ -n "$file" ]; then
parse $version < "$file"
else
parse $version
fi

View File

@@ -5,16 +5,17 @@ kotlin.js.generate.externals=true
kotlin.incremental=true
kotlin.incremental.js=true
kotlin_version=1.4.0
kotlin_version=1.4.10
kotlin_coroutines_version=1.3.9
kotlin_serialisation_runtime_version=1.0.0-RC
klock_version=1.12.0
uuid_version=0.2.1
kotlin_serialisation_runtime_version=1.0.0-RC2
klock_version=1.12.1
uuid_version=0.2.2
ktor_version=1.4.0
javax_activation_version=1.1.1
library_group=com.github.insanusmokrassar
library_version=0.28.0
library_version=0.28.3
gradle_bintray_plugin_version=1.8.5
github_release_plugin_version=2.2.12

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.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip