Merge pull request #457 from InsanusMokrassar/0.35.8

0.35.8
This commit is contained in:
InsanusMokrassar 2021-09-08 22:43:23 +06:00 committed by GitHub
commit 3f1b018808
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 113 additions and 23 deletions

View File

@ -1,5 +1,20 @@
# TelegramBotAPI changelog
## 0.35.8
* `Common`:
* `Version`:
* `MicroUtils`: `0.5.24` -> `0.5.25`
* `UUID`: `0.3.0` -> `0.3.1`
* `Core`:
* `MultipartRequestCallFactory` now will use file name as multipart `filename` parameter instead of generated
filename
* New extension `MPPFile#asMultipartFile`
* `API`
* Fixes in `TelegramBot#withAction`
* `Behaviour Builder`:
* New extensions `BehaviourContext#commandWithArgs` and `BehaviourContext#onCommandWithArgs`
## 0.35.7
* `Common`:

View File

@ -9,14 +9,14 @@ kotlin_version=1.5.30
kotlin_coroutines_version=1.5.2
kotlin_serialisation_runtime_version=1.2.2
klock_version=2.4.1
uuid_version=0.3.0
uuid_version=0.3.1
ktor_version=1.6.3
micro_utils_version=0.5.24
micro_utils_version=0.5.25
javax_activation_version=1.1.1
library_group=dev.inmo
library_version=0.35.7
library_version=0.35.8
github_release_plugin_version=2.2.12

View File

@ -24,7 +24,7 @@ class MultipartRequestCallFactory : AbstractRequestCallFactory() {
is MultipartFile -> appendInput(
key,
Headers.build {
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
append(HttpHeaders.ContentDisposition, "filename=${value.filename}")
},
block = value.file::input
)

View File

@ -1,13 +1,26 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.tgbotapi.utils.*
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.Input
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* Common type for all files in Telegram Bot API which can be sent via requests like [dev.inmo.tgbotapi.requests.send.media.SendDocument].
* You may use methods like [MPPFile.asMultipartFile] when you want to send files from your file system, but you should
* remember about [restrictions][https://core.telegram.org/bots/api#sending-files] in Telegram for bots. In case you
* wish to send file by its url, use [FileId] and pass your url as [FileId.fileId]
*
* @see MPPFile.asMultipartFile
* @see ByteArray.asMultipartFile
* @see ByteReadChannel.asMultipartFile
* @see ByteReadChannelAllocator.asMultipartFile
*/
@Serializable(InputFileSerializer::class)
sealed class InputFile {
abstract val fileId: String
@ -75,3 +88,5 @@ suspend inline fun ByteReadChannel.asMultipartFile(
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
fileName: String
) = this.invoke().asMultipartFile(fileName)
expect suspend fun MPPFile.asMultipartFile(): MultipartFile

View File

@ -0,0 +1,8 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.micro_utils.common.*
import io.ktor.utils.io.ByteReadChannel
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = ByteReadChannel(bytes()).asMultipartFile(
filename.name
)

View File

@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.micro_utils.common.MPPFile
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = toInputFile()

View File

@ -1,13 +1,13 @@
package dev.inmo.tgbotapi.extensions.api.send
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
import dev.inmo.micro_utils.coroutines.*
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.send.SendAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.actions.*
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import kotlinx.coroutines.*
import kotlin.coroutines.coroutineContext
private const val refreshTime: MilliSeconds = (botActionActualityTime - 1) * 1000L
typealias TelegramBotActionCallback<T> = suspend TelegramBot.() -> T
@ -16,21 +16,17 @@ suspend fun <T> TelegramBot.withAction(
actionRequest: SendAction,
block: TelegramBotActionCallback<T>
): T {
val botActionJob = supervisorScope {
launch {
while (isActive) {
delay(refreshTime)
safelyWithoutExceptions {
execute(actionRequest)
}
val botActionJob = CoroutineScope(coroutineContext).launch {
while (isActive) {
delay(refreshTime)
safelyWithoutExceptions {
execute(actionRequest)
}
}
}
return try {
safely { block() }
} finally {
botActionJob.cancel()
}
val result = safelyWithResult { block() }
botActionJob.cancel()
return result.getOrThrow()
}
suspend fun <T> TelegramBot.withAction(

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.filter
typealias BehaviourContextReceiver<T> = suspend BehaviourContext.() -> T
typealias BehaviourContextAndTypeReceiver<T, I> = suspend BehaviourContext.(I) -> T
typealias BehaviourContextAndTwoTypesReceiver<T, I1, I2> = suspend BehaviourContext.(I1, I2) -> T
/**
* This class contains all necessary tools for work with bots and especially for [buildBehaviour]

View File

@ -1,10 +1,10 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asBotCommandTextSource
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.TextContent
import kotlinx.coroutines.Job
@ -33,6 +33,7 @@ suspend fun BehaviourContext.command(
markerFactory,
scenarioReceiver
)
suspend fun BehaviourContext.command(
command: String,
requireOnlyCommandInMessage: Boolean = true,
@ -59,3 +60,53 @@ suspend inline fun BehaviourContext.onCommand(
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
suspend fun BehaviourContext.commandWithArgs(
commandRegex: Regex,
includeFilterByChatInBehaviourSubContext: Boolean = true,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
) = command(
commandRegex,
requireOnlyCommandInMessage = false,
includeFilterByChatInBehaviourSubContext = includeFilterByChatInBehaviourSubContext,
additionalFilter = additionalFilter,
markerFactory = markerFactory
) {
val args = it.parseCommandsWithParams().let { commandsWithArgs ->
val key = commandsWithArgs.keys.firstOrNull { it.matches(commandRegex) } ?: return@let null
commandsWithArgs[key]
} ?: emptyArray()
scenarioReceiver(it, args)
}
suspend fun BehaviourContext.commandWithArgs(
command: String,
includeFilterByChatInBehaviourSubContext: Boolean = true,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
) = commandWithArgs(
command.toRegex(),
includeFilterByChatInBehaviourSubContext = includeFilterByChatInBehaviourSubContext,
additionalFilter = additionalFilter,
markerFactory = markerFactory,
scenarioReceiver = scenarioReceiver
)
suspend inline fun BehaviourContext.onCommandWithArgs(
commandRegex: Regex,
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
): Job = commandWithArgs(commandRegex, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
suspend inline fun BehaviourContext.onCommandWithArgs(
command: String,
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
): Job = onCommandWithArgs(command.toRegex(), includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)

View File

@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.RequestsExecutor
import dev.inmo.tgbotapi.requests.abstracts.Request
import kotlinx.coroutines.*
import kotlin.coroutines.coroutineContext
fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>,
@ -16,9 +17,7 @@ fun <T: Any> RequestsExecutor.executeAsync(
suspend fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>
): Deferred<T> = coroutineScope {
executeAsync(request, this)
}
): Deferred<T> = executeAsync(request, CoroutineScope(coroutineContext))
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
request: Request<T>,