mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-11-22 07:15:45 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53800d49bf | |||
| d83e3eb10a | |||
| 66b4d06064 | |||
| 4fab01b2a2 | |||
| b81086c4bb | |||
| d776071cac | |||
| 5f33d05deb | |||
| 912cc7217c | |||
| 96e00f6e31 | |||
| f8ea5f9515 | |||
| 9f11c4f1c4 | |||
| 9c91980d5d | |||
| 7376eb5b10 | |||
| 6654f27f9d | |||
| 83edda2dfe |
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,5 +1,30 @@
|
|||||||
# TelegramBotAPI changelog
|
# TelegramBotAPI changelog
|
||||||
|
|
||||||
|
## 0.30.3
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `MicroUtils`: `0.3.0` -> `0.3.1`
|
||||||
|
* `Core`:
|
||||||
|
* New type of requests exceptions `TooMuchRequestsException`. In fact it will be rare case when you will get this
|
||||||
|
exception
|
||||||
|
* `EmptyLimiter` has been renamed to `ExceptionsOnlyLimiter` and currently will stop requests after
|
||||||
|
`TooMuchRequestsException` happen until retry time is actual
|
||||||
|
* Now `ExceptionsOnlyLimiter` (previously `EmptyLimiter`) is a class
|
||||||
|
* `AbstractRequestCallFactory` currently will not look at the response and wait if it have `RetryAfter` error. New
|
||||||
|
behaviour aimed on delegating of this work to `RequestsLimiter`
|
||||||
|
|
||||||
|
## 0.30.2
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `Ktor`: `1.4.1` -> `1.4.2`
|
||||||
|
* `Core`:
|
||||||
|
* New sealed class `SetWebhookRequest` which can be used in `SetWebhook` requests
|
||||||
|
* `Utils`:
|
||||||
|
* Extensions `setWebhookInfoAndStartListenWebhooks` has been united in one extension with `SetWebhookRequest`
|
||||||
|
incoming parameter
|
||||||
|
|
||||||
## 0.30.1
|
## 0.30.1
|
||||||
|
|
||||||
* `Common`:
|
* `Common`:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
|
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
|
||||||
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| Useful links | [](https://t.me/InMoTelegramBotAPI) [](https://tgbotapi.inmo.dev/docs/index.html) [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/), [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
| Useful links | [](https://t.me/InMoTelegramBotAPI) [](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [](https://tgbotapi.inmo.dev/docs/index.html) [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/), [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
||||||
| TelegramBotAPI Core status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
|
| TelegramBotAPI Core status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
|
||||||
| TelegramBotAPI Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
|
| TelegramBotAPI Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
|
||||||
| TelegramBotAPI Util Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
|
| TelegramBotAPI Util Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
|
||||||
|
|||||||
20
badges/template.svg
Normal file
20
badges/template.svg
Normal 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="M35 0h69v20H35z"/>
|
||||||
|
<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)">Bot</text>
|
||||||
|
<text x="175" y="140" transform="scale(.1)">Bot</text>
|
||||||
|
<text x="690" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Template</text>
|
||||||
|
<text x="690" y="140" transform="scale(.1)">Template</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1016 B |
@@ -10,14 +10,14 @@ kotlin_coroutines_version=1.4.1
|
|||||||
kotlin_serialisation_runtime_version=1.0.1
|
kotlin_serialisation_runtime_version=1.0.1
|
||||||
klock_version=1.12.1
|
klock_version=1.12.1
|
||||||
uuid_version=0.2.2
|
uuid_version=0.2.2
|
||||||
ktor_version=1.4.1
|
ktor_version=1.4.2
|
||||||
|
|
||||||
micro_utils_version=0.3.0
|
micro_utils_version=0.3.1
|
||||||
|
|
||||||
javax_activation_version=1.1.1
|
javax_activation_version=1.1.1
|
||||||
|
|
||||||
library_group=dev.inmo
|
library_group=dev.inmo
|
||||||
library_version=0.30.1
|
library_version=0.30.3
|
||||||
|
|
||||||
gradle_bintray_plugin_version=1.8.5
|
gradle_bintray_plugin_version=1.8.5
|
||||||
github_release_plugin_version=2.2.12
|
github_release_plugin_version=2.2.12
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import dev.inmo.micro_utils.coroutines.safely
|
|||||||
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
||||||
import dev.inmo.tgbotapi.bot.Ktor.base.*
|
import dev.inmo.tgbotapi.bot.Ktor.base.*
|
||||||
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
||||||
import dev.inmo.tgbotapi.bot.settings.limiters.EmptyLimiter
|
import dev.inmo.tgbotapi.bot.settings.limiters.*
|
||||||
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
|
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
import dev.inmo.tgbotapi.types.Response
|
import dev.inmo.tgbotapi.types.Response
|
||||||
import dev.inmo.tgbotapi.utils.*
|
import dev.inmo.tgbotapi.utils.*
|
||||||
@@ -19,7 +18,7 @@ class KtorRequestsExecutor(
|
|||||||
client: HttpClient = HttpClient(),
|
client: HttpClient = HttpClient(),
|
||||||
callsFactories: List<KtorCallFactory> = emptyList(),
|
callsFactories: List<KtorCallFactory> = emptyList(),
|
||||||
excludeDefaultFactories: Boolean = false,
|
excludeDefaultFactories: Boolean = false,
|
||||||
private val requestsLimiter: RequestLimiter = EmptyLimiter,
|
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter(),
|
||||||
private val jsonFormatter: Json = nonstrictJsonFormat
|
private val jsonFormatter: Json = nonstrictJsonFormat
|
||||||
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
||||||
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.bot.Ktor.base
|
package dev.inmo.tgbotapi.bot.Ktor.base
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.safely
|
||||||
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
||||||
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
||||||
import dev.inmo.tgbotapi.requests.GetUpdates
|
import dev.inmo.tgbotapi.requests.GetUpdates
|
||||||
@@ -51,23 +52,17 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
|
|||||||
val content = response.receive<String>()
|
val content = response.receive<String>()
|
||||||
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
||||||
|
|
||||||
return (responseObject.result?.let {
|
return safely {
|
||||||
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
|
(responseObject.result?.let {
|
||||||
} ?: responseObject.parameters?.let {
|
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
|
||||||
val error = it.error
|
} ?: response.let {
|
||||||
if (error is RetryAfterError) {
|
throw newRequestException(
|
||||||
delay(error.leftToRetry)
|
responseObject,
|
||||||
makeCall(client, urlsKeeper, request, jsonFormatter)
|
content,
|
||||||
} else {
|
"Can't get result object from $content"
|
||||||
null
|
)
|
||||||
}
|
})
|
||||||
} ?: response.let {
|
}
|
||||||
throw newRequestException(
|
|
||||||
responseObject,
|
|
||||||
content,
|
|
||||||
"Can't get result object from $content"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.bot.exceptions
|
package dev.inmo.tgbotapi.bot.exceptions
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.Response
|
import com.soywiz.klock.DateTime
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import io.ktor.utils.io.errors.IOException
|
import io.ktor.utils.io.errors.IOException
|
||||||
|
|
||||||
fun newRequestException(
|
fun newRequestException(
|
||||||
@@ -16,6 +17,13 @@ fun newRequestException(
|
|||||||
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)
|
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)
|
||||||
description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(response, plainAnswer, message, cause)
|
description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(response, plainAnswer, message, cause)
|
||||||
description.contains("wrong file identifier") -> WrongFileIdentifierException(response, plainAnswer, message, cause)
|
description.contains("wrong file identifier") -> WrongFileIdentifierException(response, plainAnswer, message, cause)
|
||||||
|
description.contains("Too Many Requests") -> TooMuchRequestsException(
|
||||||
|
(response.parameters ?.error as? RetryAfterError) ?: RetryAfterError(60, DateTime.now().unixMillisLong),
|
||||||
|
response,
|
||||||
|
plainAnswer,
|
||||||
|
message,
|
||||||
|
cause
|
||||||
|
)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
} ?: CommonRequestException(response, plainAnswer, message, cause)
|
} ?: CommonRequestException(response, plainAnswer, message, cause)
|
||||||
@@ -49,3 +57,6 @@ class InvalidPhotoDimensionsException(response: Response, plainAnswer: String, m
|
|||||||
|
|
||||||
class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
||||||
RequestException(response, plainAnswer, message, cause)
|
RequestException(response, plainAnswer, message, cause)
|
||||||
|
|
||||||
|
class TooMuchRequestsException(val retryAfter: RetryAfterError, response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
||||||
|
RequestException(response, plainAnswer, message, cause)
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package dev.inmo.tgbotapi.bot.settings.limiters
|
|
||||||
|
|
||||||
object EmptyLimiter : RequestLimiter {
|
|
||||||
override suspend fun <T> limit(block: suspend () -> T): T = block()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package dev.inmo.tgbotapi.bot.settings.limiters
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.safely
|
||||||
|
import dev.inmo.tgbotapi.bot.exceptions.TooMuchRequestsException
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import io.ktor.client.features.ClientRequestException
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This limiter will limit requests only after getting a [RetryAfterError] or [ClientRequestException] with
|
||||||
|
* [HttpStatusCode.TooManyRequests] status code. Important thing is that in case if some of block has been blocked, all
|
||||||
|
* the others will wait until it will be possible to be called
|
||||||
|
*
|
||||||
|
* @param defaultTooManyRequestsDelay This parameter will be used in case of getting [ClientRequestException] with
|
||||||
|
* [HttpStatusCode.TooManyRequests] as a parameter for delay like it would be [TooMuchRequestsException]. The reason of
|
||||||
|
* it is that in [ClientRequestException] there is no information about required delay between requests
|
||||||
|
*/
|
||||||
|
class ExceptionsOnlyLimiter(
|
||||||
|
private val defaultTooManyRequestsDelay: MilliSeconds = 1000L
|
||||||
|
) : RequestLimiter {
|
||||||
|
private val lockState = MutableStateFlow(false)
|
||||||
|
private suspend fun lock(timeMillis: MilliSeconds) {
|
||||||
|
try {
|
||||||
|
safely {
|
||||||
|
lockState.emit(true)
|
||||||
|
delay(timeMillis)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lockState.emit(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun <T> limit(block: suspend () -> T): T {
|
||||||
|
while (true) {
|
||||||
|
lockState.first { !it }
|
||||||
|
val result = safely({
|
||||||
|
when (it) {
|
||||||
|
is TooMuchRequestsException -> {
|
||||||
|
lock(it.retryAfter.leftToRetry)
|
||||||
|
Result.failure(it)
|
||||||
|
}
|
||||||
|
is ClientRequestException -> {
|
||||||
|
if (it.response.status == HttpStatusCode.TooManyRequests) {
|
||||||
|
lock(defaultTooManyRequestsDelay)
|
||||||
|
} else {
|
||||||
|
throw it
|
||||||
|
}
|
||||||
|
Result.failure(it)
|
||||||
|
}
|
||||||
|
else -> throw it
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Result.success(block())
|
||||||
|
}
|
||||||
|
if (result.isSuccess) {
|
||||||
|
return result.getOrNull()!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Renamed", ReplaceWith("ExceptionsOnlyLimiter", "dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter"))
|
||||||
|
typealias EmptyLimiter = ExceptionsOnlyLimiter
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.requests.webhook
|
package dev.inmo.tgbotapi.requests.webhook
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.*
|
import dev.inmo.tgbotapi.requests.abstracts.*
|
||||||
import dev.inmo.tgbotapi.requests.send.media.base.DataRequest
|
import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||||
import dev.inmo.tgbotapi.requests.send.media.base.MultipartRequestImpl
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
@@ -13,14 +12,15 @@ private fun correctWebhookUrl(sourceUrl: String) = if (sourceUrl.contains("://")
|
|||||||
"https://$sourceUrl"
|
"https://$sourceUrl"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SetWebhook(
|
sealed class SetWebhookRequest : Request<Boolean>
|
||||||
|
class MultipartSetWebhookRequest(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: MultipartFile,
|
certificate: MultipartFile,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
dropPendingUpdates: Boolean? = null
|
dropPendingUpdates: Boolean? = null
|
||||||
): MultipartRequestImpl<SetWebhook, Map<String, MultipartFile>, Boolean> = MultipartRequestImpl(
|
) : SetWebhookRequest(), MultipartRequest<Boolean> by MultipartRequestImpl(
|
||||||
SetWebhook(
|
SetWebhook(
|
||||||
correctWebhookUrl(url),
|
correctWebhookUrl(url),
|
||||||
null as String?,
|
null as String?,
|
||||||
@@ -32,6 +32,22 @@ fun SetWebhook(
|
|||||||
mapOf(certificateField to certificate)
|
mapOf(certificateField to certificate)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun SetWebhook(
|
||||||
|
url: String,
|
||||||
|
certificate: MultipartFile,
|
||||||
|
ipAddress: String? = null,
|
||||||
|
maxAllowedConnections: Int? = null,
|
||||||
|
allowedUpdates: List<String>? = null,
|
||||||
|
dropPendingUpdates: Boolean? = null
|
||||||
|
): MultipartSetWebhookRequest = MultipartSetWebhookRequest(
|
||||||
|
correctWebhookUrl(url),
|
||||||
|
certificate,
|
||||||
|
ipAddress,
|
||||||
|
maxAllowedConnections,
|
||||||
|
allowedUpdates,
|
||||||
|
dropPendingUpdates
|
||||||
|
)
|
||||||
|
|
||||||
fun SetWebhook(
|
fun SetWebhook(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: FileId,
|
certificate: FileId,
|
||||||
@@ -63,7 +79,7 @@ fun SetWebhook(
|
|||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
dropPendingUpdates: Boolean? = null
|
dropPendingUpdates: Boolean? = null
|
||||||
): Request<Boolean> = when (certificate) {
|
) = when (certificate) {
|
||||||
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
||||||
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
||||||
}
|
}
|
||||||
@@ -82,7 +98,7 @@ fun SetWebhook(
|
|||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
dropPendingUpdates: Boolean? = null
|
dropPendingUpdates: Boolean? = null
|
||||||
): Request<Boolean> = SetWebhook(
|
) = SetWebhook(
|
||||||
correctWebhookUrl(url),
|
correctWebhookUrl(url),
|
||||||
null,
|
null,
|
||||||
ipAddress,
|
ipAddress,
|
||||||
@@ -112,7 +128,7 @@ data class SetWebhook internal constructor(
|
|||||||
val allowedUpdates: List<String>? = null,
|
val allowedUpdates: List<String>? = null,
|
||||||
@SerialName(dropPendingUpdatesField)
|
@SerialName(dropPendingUpdatesField)
|
||||||
val dropPendingUpdates: Boolean? = null
|
val dropPendingUpdates: Boolean? = null
|
||||||
) : DataRequest<Boolean> {
|
) : SetWebhookRequest(), DataRequest<Boolean> {
|
||||||
override fun method(): String = "setWebhook"
|
override fun method(): String = "setWebhook"
|
||||||
override val resultDeserializer: DeserializationStrategy<Boolean>
|
override val resultDeserializer: DeserializationStrategy<Boolean>
|
||||||
get() = Boolean.serializer()
|
get() = Boolean.serializer()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ typealias GooglePlaceId = String
|
|||||||
typealias GooglePlaceType = String
|
typealias GooglePlaceType = String
|
||||||
|
|
||||||
typealias Seconds = Int
|
typealias Seconds = Int
|
||||||
|
typealias MilliSeconds = Long
|
||||||
typealias LongSeconds = Long
|
typealias LongSeconds = Long
|
||||||
|
|
||||||
typealias Meters = Float
|
typealias Meters = Float
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.soywiz.klock.DateTime
|
|||||||
sealed class RequestError
|
sealed class RequestError
|
||||||
|
|
||||||
data class RetryAfterError(
|
data class RetryAfterError(
|
||||||
val seconds: Long,
|
val seconds: Seconds,
|
||||||
val startCountingMillis: Long
|
val startCountingMillis: Long
|
||||||
) : RequestError() {
|
) : RequestError() {
|
||||||
val canContinue = (seconds * 1000L) + startCountingMillis
|
val canContinue = (seconds * 1000L) + startCountingMillis
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ data class ResponseParametersRaw(
|
|||||||
@SerialName("migrate_to_chat_id")
|
@SerialName("migrate_to_chat_id")
|
||||||
private val migrateToChatId: ChatId? = null,
|
private val migrateToChatId: ChatId? = null,
|
||||||
@SerialName("retry_after")
|
@SerialName("retry_after")
|
||||||
private val retryAfter: Long? = null
|
private val retryAfter: Seconds? = null
|
||||||
) {
|
) {
|
||||||
@Transient
|
@Transient
|
||||||
private val createTime: Long = DateTime.now().unixMillisLong
|
private val createTime: Long = DateTime.now().unixMillisLong
|
||||||
|
|||||||
@@ -40,11 +40,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
api project(":tgbotapi.core")
|
||||||
api "${project.group}:tgbotapi.core:$library_version"
|
|
||||||
} else {
|
|
||||||
api project(":tgbotapi.core")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,11 +40,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
api project(":tgbotapi.core")
|
||||||
api "${project.group}:tgbotapi.core:$library_version"
|
|
||||||
} else {
|
|
||||||
api project(":tgbotapi.core")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import dev.inmo.micro_utils.coroutines.safely
|
|||||||
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
||||||
import dev.inmo.tgbotapi.extensions.utils.nonstrictJsonFormat
|
import dev.inmo.tgbotapi.extensions.utils.nonstrictJsonFormat
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter
|
import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
import dev.inmo.tgbotapi.requests.webhook.SetWebhookRequest
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
|
||||||
import dev.inmo.tgbotapi.requests.send.media.base.MultipartRequestImpl
|
|
||||||
import dev.inmo.tgbotapi.requests.webhook.SetWebhook
|
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy
|
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy
|
||||||
import dev.inmo.tgbotapi.updateshandlers.*
|
import dev.inmo.tgbotapi.updateshandlers.*
|
||||||
@@ -67,7 +64,7 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
* Setting up ktor server
|
||||||
*
|
*
|
||||||
* @param listenPort port which will be listen by bot
|
* @param listenPort port which will be listen by bot
|
||||||
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
||||||
@@ -119,27 +116,8 @@ fun startListenWebhooks(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhooks(
|
|
||||||
listenPort: Int,
|
|
||||||
engineFactory: ApplicationEngineFactory<*, *>,
|
|
||||||
setWebhookRequest: Request<Boolean>,
|
|
||||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
|
||||||
listenHost: String = "0.0.0.0",
|
|
||||||
listenRoute: String? = null,
|
|
||||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
|
||||||
block: UpdateReceiver<Update>
|
|
||||||
): ApplicationEngine {
|
|
||||||
return try {
|
|
||||||
execute(setWebhookRequest)
|
|
||||||
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
* Setting up ktor server, set webhook info via [SetWebhookRequest] request.
|
||||||
*
|
*
|
||||||
* @param listenPort port which will be listen by bot
|
* @param listenPort port which will be listen by bot
|
||||||
* @param listenRoute address to listen by bot
|
* @param listenRoute address to listen by bot
|
||||||
@@ -153,55 +131,16 @@ private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhook
|
|||||||
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||||
listenPort: Int,
|
listenPort: Int,
|
||||||
engineFactory: ApplicationEngineFactory<*, *>,
|
engineFactory: ApplicationEngineFactory<*, *>,
|
||||||
setWebhookRequest: SetWebhook,
|
setWebhookRequest: SetWebhookRequest,
|
||||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
exceptionsHandler: ExceptionHandler<Unit> = {},
|
||||||
listenHost: String = "0.0.0.0",
|
listenHost: String = "0.0.0.0",
|
||||||
listenRoute: String = "/",
|
listenRoute: String = "/",
|
||||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
block: UpdateReceiver<Update>
|
block: UpdateReceiver<Update>
|
||||||
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
|
): ApplicationEngine = try {
|
||||||
listenPort,
|
execute(setWebhookRequest)
|
||||||
engineFactory,
|
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
|
||||||
setWebhookRequest as Request<Boolean>,
|
} catch (e: Exception) {
|
||||||
exceptionsHandler,
|
throw e
|
||||||
listenHost,
|
}
|
||||||
listenRoute,
|
|
||||||
privateKeyConfig,
|
|
||||||
scope,
|
|
||||||
block
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
|
||||||
*
|
|
||||||
* @param listenPort port which will be listen by bot
|
|
||||||
* @param listenRoute address to listen by bot
|
|
||||||
* @param scope Scope which will be used for
|
|
||||||
*
|
|
||||||
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
|
||||||
* @see UpdatesFilter
|
|
||||||
* @see UpdatesFilter.asUpdateReceiver
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
|
||||||
listenPort: Int,
|
|
||||||
engineFactory: ApplicationEngineFactory<*, *>,
|
|
||||||
setWebhookRequest: MultipartRequestImpl<SetWebhook, Map<String, MultipartFile>, Boolean>,
|
|
||||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
|
||||||
listenHost: String = "0.0.0.0",
|
|
||||||
listenRoute: String? = null,
|
|
||||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
|
||||||
block: UpdateReceiver<Update>
|
|
||||||
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
|
|
||||||
listenPort,
|
|
||||||
engineFactory,
|
|
||||||
setWebhookRequest as Request<Boolean>,
|
|
||||||
exceptionsHandler,
|
|
||||||
listenHost,
|
|
||||||
listenRoute,
|
|
||||||
privateKeyConfig,
|
|
||||||
scope,
|
|
||||||
block
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -40,15 +40,9 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
api project(":tgbotapi.core")
|
||||||
api "${project.group}:tgbotapi.core:$library_version"
|
api project(":tgbotapi.extensions.api")
|
||||||
api "${project.group}:tgbotapi.extensions.api:$library_version"
|
api project(":tgbotapi.extensions.utils")
|
||||||
api "${project.group}:tgbotapi.extensions.utils:$library_version"
|
|
||||||
} else {
|
|
||||||
api project(":tgbotapi.core")
|
|
||||||
api project(":tgbotapi.extensions.api")
|
|
||||||
api project(":tgbotapi.extensions.utils")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user