2020-10-04 11:06:30 +00:00
|
|
|
package dev.inmo.tgbotapi.bot.Ktor
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2020-11-07 07:42:10 +00:00
|
|
|
import dev.inmo.micro_utils.coroutines.safely
|
2020-10-04 11:06:30 +00:00
|
|
|
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
|
|
|
import dev.inmo.tgbotapi.bot.Ktor.base.*
|
2020-11-17 10:06:25 +00:00
|
|
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
2020-10-04 11:06:30 +00:00
|
|
|
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
2022-04-11 06:46:33 +00:00
|
|
|
import dev.inmo.tgbotapi.bot.ktor.KtorPipelineStepsHolder
|
2021-01-09 14:59:37 +00:00
|
|
|
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
|
|
|
|
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
|
2020-10-04 11:06:30 +00:00
|
|
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
|
|
|
import dev.inmo.tgbotapi.types.Response
|
|
|
|
import dev.inmo.tgbotapi.utils.*
|
2018-12-26 08:07:24 +00:00
|
|
|
import io.ktor.client.HttpClient
|
2020-03-19 05:10:18 +00:00
|
|
|
import io.ktor.client.features.*
|
2020-01-15 06:28:06 +00:00
|
|
|
import io.ktor.client.statement.readText
|
2019-02-21 06:21:33 +00:00
|
|
|
import kotlinx.serialization.json.Json
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2021-08-09 17:22:08 +00:00
|
|
|
@RiskFeature
|
|
|
|
fun createTelegramBotDefaultKtorCallRequestsFactories() = listOf(
|
|
|
|
SimpleRequestCallFactory(),
|
|
|
|
MultipartRequestCallFactory(),
|
|
|
|
DownloadFileRequestCallFactory,
|
|
|
|
DownloadFileChannelRequestCallFactory
|
|
|
|
)
|
|
|
|
|
2018-12-26 08:07:24 +00:00
|
|
|
class KtorRequestsExecutor(
|
2019-07-25 08:25:18 +00:00
|
|
|
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
2020-03-17 15:24:04 +00:00
|
|
|
client: HttpClient = HttpClient(),
|
2018-12-26 08:07:24 +00:00
|
|
|
callsFactories: List<KtorCallFactory> = emptyList(),
|
2019-01-24 02:36:44 +00:00
|
|
|
excludeDefaultFactories: Boolean = false,
|
2020-11-11 05:23:24 +00:00
|
|
|
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter(),
|
2022-04-11 06:46:33 +00:00
|
|
|
private val jsonFormatter: Json = nonstrictJsonFormat,
|
2022-04-16 17:58:24 +00:00
|
|
|
private val pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder
|
2019-07-25 08:25:18 +00:00
|
|
|
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
2018-12-26 08:07:24 +00:00
|
|
|
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
|
|
|
if (!excludeDefaultFactories) {
|
2021-08-09 17:22:08 +00:00
|
|
|
this + createTelegramBotDefaultKtorCallRequestsFactories()
|
2018-12-26 08:07:24 +00:00
|
|
|
} else {
|
|
|
|
this
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 15:24:04 +00:00
|
|
|
private val client = client.config {
|
2020-03-19 05:10:18 +00:00
|
|
|
if (client.feature(HttpTimeout) == null) {
|
|
|
|
install(HttpTimeout)
|
|
|
|
}
|
2020-03-17 15:24:04 +00:00
|
|
|
}
|
2019-08-17 05:50:46 +00:00
|
|
|
|
2020-03-17 15:24:04 +00:00
|
|
|
override suspend fun <T : Any> execute(request: Request<T>): T {
|
2022-04-11 08:41:02 +00:00
|
|
|
return runCatching {
|
|
|
|
safely(
|
|
|
|
{ e ->
|
|
|
|
pipelineStepsHolder.onRequestException(request, e) ?.let { return@safely it }
|
2022-04-11 06:46:33 +00:00
|
|
|
|
2022-04-11 08:41:02 +00:00
|
|
|
throw if (e is ClientRequestException) {
|
|
|
|
val content = e.response.readText()
|
|
|
|
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
|
|
|
newRequestException(
|
|
|
|
responseObject,
|
|
|
|
content,
|
|
|
|
"Can't get result object from $content"
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
e
|
2019-12-13 17:54:02 +00:00
|
|
|
}
|
2022-04-11 08:41:02 +00:00
|
|
|
|
2020-04-13 06:40:14 +00:00
|
|
|
}
|
2022-04-11 08:41:02 +00:00
|
|
|
) {
|
|
|
|
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
|
|
|
|
requestsLimiter.limit {
|
|
|
|
var result: T? = null
|
|
|
|
lateinit var factoryHandledRequest: KtorCallFactory
|
|
|
|
for (potentialFactory in callsFactories) {
|
|
|
|
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
|
|
|
|
result = potentialFactory.makeCall(
|
|
|
|
client,
|
|
|
|
telegramAPIUrlsKeeper,
|
|
|
|
request,
|
|
|
|
jsonFormatter
|
|
|
|
)
|
|
|
|
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
|
|
|
|
if (result != null) {
|
|
|
|
factoryHandledRequest = potentialFactory
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-03-17 15:24:04 +00:00
|
|
|
|
2022-04-11 08:41:02 +00:00
|
|
|
result ?.let {
|
|
|
|
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
|
|
|
|
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
|
|
|
|
}
|
2019-12-13 17:54:02 +00:00
|
|
|
}
|
2022-04-11 08:41:02 +00:00
|
|
|
}.let {
|
|
|
|
pipelineStepsHolder.onRequestReturnResult(it, request, callsFactories)
|
2018-12-26 08:07:24 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-22 23:46:19 +00:00
|
|
|
|
|
|
|
override fun close() {
|
|
|
|
client.close()
|
|
|
|
}
|
2018-12-26 08:07:24 +00:00
|
|
|
}
|
2022-04-21 15:48:25 +00:00
|
|
|
|
|
|
|
class KtorRequestsExecutorBuilder(
|
|
|
|
var telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
|
|
|
|
) {
|
|
|
|
var client: HttpClient = HttpClient()
|
|
|
|
var callsFactories: List<KtorCallFactory> = emptyList()
|
|
|
|
var excludeDefaultFactories: Boolean = false
|
|
|
|
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter()
|
|
|
|
var jsonFormatter: Json = nonstrictJsonFormat
|
|
|
|
|
|
|
|
fun build() = KtorRequestsExecutor(telegramAPIUrlsKeeper, client, callsFactories, excludeDefaultFactories, requestsLimiter, jsonFormatter)
|
|
|
|
}
|
|
|
|
|
|
|
|
inline fun telegramBot(
|
|
|
|
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
|
|
|
builder: KtorRequestsExecutorBuilder.() -> Unit = {}
|
|
|
|
): TelegramBot = KtorRequestsExecutorBuilder(telegramAPIUrlsKeeper).apply(builder).build()
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shortcut for [telegramBot]
|
|
|
|
*/
|
|
|
|
@Suppress("NOTHING_TO_INLINE")
|
|
|
|
inline fun telegramBot(
|
|
|
|
token: String,
|
|
|
|
apiUrl: String = telegramBotAPIDefaultUrl,
|
2022-05-02 07:21:43 +00:00
|
|
|
testServer: Boolean = false,
|
2022-04-21 15:48:25 +00:00
|
|
|
builder: KtorRequestsExecutorBuilder.() -> Unit = {}
|
2022-05-02 07:21:43 +00:00
|
|
|
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, testServer, apiUrl), builder)
|