mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-22 16:23:48 +00:00
commit
3f1b018808
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,5 +1,20 @@
|
|||||||
# TelegramBotAPI changelog
|
# 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
|
## 0.35.7
|
||||||
|
|
||||||
* `Common`:
|
* `Common`:
|
||||||
|
@ -9,14 +9,14 @@ kotlin_version=1.5.30
|
|||||||
kotlin_coroutines_version=1.5.2
|
kotlin_coroutines_version=1.5.2
|
||||||
kotlin_serialisation_runtime_version=1.2.2
|
kotlin_serialisation_runtime_version=1.2.2
|
||||||
klock_version=2.4.1
|
klock_version=2.4.1
|
||||||
uuid_version=0.3.0
|
uuid_version=0.3.1
|
||||||
ktor_version=1.6.3
|
ktor_version=1.6.3
|
||||||
|
|
||||||
micro_utils_version=0.5.24
|
micro_utils_version=0.5.25
|
||||||
|
|
||||||
javax_activation_version=1.1.1
|
javax_activation_version=1.1.1
|
||||||
|
|
||||||
library_group=dev.inmo
|
library_group=dev.inmo
|
||||||
library_version=0.35.7
|
library_version=0.35.8
|
||||||
|
|
||||||
github_release_plugin_version=2.2.12
|
github_release_plugin_version=2.2.12
|
||||||
|
@ -24,7 +24,7 @@ class MultipartRequestCallFactory : AbstractRequestCallFactory() {
|
|||||||
is MultipartFile -> appendInput(
|
is MultipartFile -> appendInput(
|
||||||
key,
|
key,
|
||||||
Headers.build {
|
Headers.build {
|
||||||
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
|
append(HttpHeaders.ContentDisposition, "filename=${value.filename}")
|
||||||
},
|
},
|
||||||
block = value.file::input
|
block = value.file::input
|
||||||
)
|
)
|
||||||
|
@ -1,13 +1,26 @@
|
|||||||
package dev.inmo.tgbotapi.requests.abstracts
|
package dev.inmo.tgbotapi.requests.abstracts
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
import dev.inmo.tgbotapi.utils.*
|
import dev.inmo.tgbotapi.utils.*
|
||||||
import io.ktor.utils.io.ByteReadChannel
|
import io.ktor.utils.io.ByteReadChannel
|
||||||
|
import io.ktor.utils.io.core.Input
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.descriptors.*
|
import kotlinx.serialization.descriptors.*
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
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)
|
@Serializable(InputFileSerializer::class)
|
||||||
sealed class InputFile {
|
sealed class InputFile {
|
||||||
abstract val fileId: String
|
abstract val fileId: String
|
||||||
@ -75,3 +88,5 @@ suspend inline fun ByteReadChannel.asMultipartFile(
|
|||||||
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
|
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
|
||||||
fileName: String
|
fileName: String
|
||||||
) = this.invoke().asMultipartFile(fileName)
|
) = this.invoke().asMultipartFile(fileName)
|
||||||
|
|
||||||
|
expect suspend fun MPPFile.asMultipartFile(): MultipartFile
|
||||||
|
@ -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
|
||||||
|
)
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.tgbotapi.requests.abstracts
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
|
|
||||||
|
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = toInputFile()
|
@ -1,13 +1,13 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.api.send
|
package dev.inmo.tgbotapi.extensions.api.send
|
||||||
|
|
||||||
import dev.inmo.micro_utils.coroutines.safely
|
import dev.inmo.micro_utils.coroutines.*
|
||||||
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
|
|
||||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.requests.send.SendAction
|
import dev.inmo.tgbotapi.requests.send.SendAction
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.actions.*
|
import dev.inmo.tgbotapi.types.actions.*
|
||||||
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
|
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import kotlin.coroutines.coroutineContext
|
||||||
|
|
||||||
private const val refreshTime: MilliSeconds = (botActionActualityTime - 1) * 1000L
|
private const val refreshTime: MilliSeconds = (botActionActualityTime - 1) * 1000L
|
||||||
typealias TelegramBotActionCallback<T> = suspend TelegramBot.() -> T
|
typealias TelegramBotActionCallback<T> = suspend TelegramBot.() -> T
|
||||||
@ -16,21 +16,17 @@ suspend fun <T> TelegramBot.withAction(
|
|||||||
actionRequest: SendAction,
|
actionRequest: SendAction,
|
||||||
block: TelegramBotActionCallback<T>
|
block: TelegramBotActionCallback<T>
|
||||||
): T {
|
): T {
|
||||||
val botActionJob = supervisorScope {
|
val botActionJob = CoroutineScope(coroutineContext).launch {
|
||||||
launch {
|
while (isActive) {
|
||||||
while (isActive) {
|
delay(refreshTime)
|
||||||
delay(refreshTime)
|
safelyWithoutExceptions {
|
||||||
safelyWithoutExceptions {
|
execute(actionRequest)
|
||||||
execute(actionRequest)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return try {
|
val result = safelyWithResult { block() }
|
||||||
safely { block() }
|
botActionJob.cancel()
|
||||||
} finally {
|
return result.getOrThrow()
|
||||||
botActionJob.cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun <T> TelegramBot.withAction(
|
suspend fun <T> TelegramBot.withAction(
|
||||||
|
@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.filter
|
|||||||
|
|
||||||
typealias BehaviourContextReceiver<T> = suspend BehaviourContext.() -> T
|
typealias BehaviourContextReceiver<T> = suspend BehaviourContext.() -> T
|
||||||
typealias BehaviourContextAndTypeReceiver<T, I> = suspend BehaviourContext.(I) -> 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]
|
* This class contains all necessary tools for work with bots and especially for [buildBehaviour]
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
|
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver
|
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
|
||||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
|
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
|
||||||
import dev.inmo.tgbotapi.extensions.utils.asBotCommandTextSource
|
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.abstracts.CommonMessage
|
||||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@ -33,6 +33,7 @@ suspend fun BehaviourContext.command(
|
|||||||
markerFactory,
|
markerFactory,
|
||||||
scenarioReceiver
|
scenarioReceiver
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun BehaviourContext.command(
|
suspend fun BehaviourContext.command(
|
||||||
command: String,
|
command: String,
|
||||||
requireOnlyCommandInMessage: Boolean = true,
|
requireOnlyCommandInMessage: Boolean = true,
|
||||||
@ -59,3 +60,53 @@ suspend inline fun BehaviourContext.onCommand(
|
|||||||
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
|
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
|
||||||
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
|
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
|
||||||
): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
|
): 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)
|
||||||
|
@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.safely
|
|||||||
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import kotlin.coroutines.coroutineContext
|
||||||
|
|
||||||
fun <T: Any> RequestsExecutor.executeAsync(
|
fun <T: Any> RequestsExecutor.executeAsync(
|
||||||
request: Request<T>,
|
request: Request<T>,
|
||||||
@ -16,9 +17,7 @@ fun <T: Any> RequestsExecutor.executeAsync(
|
|||||||
|
|
||||||
suspend fun <T: Any> RequestsExecutor.executeAsync(
|
suspend fun <T: Any> RequestsExecutor.executeAsync(
|
||||||
request: Request<T>
|
request: Request<T>
|
||||||
): Deferred<T> = coroutineScope {
|
): Deferred<T> = executeAsync(request, CoroutineScope(coroutineContext))
|
||||||
executeAsync(request, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
|
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
|
||||||
request: Request<T>,
|
request: Request<T>,
|
||||||
|
Loading…
Reference in New Issue
Block a user