mirror of
				https://github.com/InsanusMokrassar/TelegramBotAPI.git
				synced 2025-11-04 06:00:15 +00:00 
			
		
		
		
	
							
								
								
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -27,6 +27,16 @@ must be regular text
 | 
				
			|||||||
* `RequestsExecutor#executeAsync(Request, CoroutineScope)` now will return `Deferred` for cases when you need result
 | 
					* `RequestsExecutor#executeAsync(Request, CoroutineScope)` now will return `Deferred` for cases when you need result
 | 
				
			||||||
* `RequestsExecutor#executeUnsafe` will automatically retry request if it was unsuccessful and retries > 0
 | 
					* `RequestsExecutor#executeUnsafe` will automatically retry request if it was unsuccessful and retries > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 0.9.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `KtorRequestsExecutor` now can use custom `JSON` string formatter (by default - non strict)
 | 
				
			||||||
 | 
					* `ResponseParameters` renamed to `Response`
 | 
				
			||||||
 | 
					* Add `RequestError` sealed class and described in documentation known errors
 | 
				
			||||||
 | 
					* Add `ResponseParametersRaw` which can create error based on input parameters
 | 
				
			||||||
 | 
					* Add `parameters` field in `Response` and remove useless fields from `Response`
 | 
				
			||||||
 | 
					* Add `leftToRetry` parameter in `RetryAfterError`
 | 
				
			||||||
 | 
					* Add handling of `RetryAfterError` in `KtorRequestsExecutor`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 0.8.5
 | 
					### 0.8.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Add extension `String#toMarkdown`
 | 
					* Add extension `String#toMarkdown`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
project.version = "0.9.2"
 | 
					project.version = "0.9.3"
 | 
				
			||||||
project.group = "com.github.insanusmokrassar"
 | 
					project.group = "com.github.insanusmokrassar"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
buildscript {
 | 
					buildscript {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,12 +7,14 @@ import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestException
 | 
				
			|||||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters.EmptyLimiter
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters.EmptyLimiter
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters.RequestLimiter
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters.RequestLimiter
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ResponseParameters
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.Response
 | 
				
			||||||
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.RetryAfterError
 | 
				
			||||||
import io.ktor.client.HttpClient
 | 
					import io.ktor.client.HttpClient
 | 
				
			||||||
import io.ktor.client.call.HttpClientCall
 | 
					import io.ktor.client.call.HttpClientCall
 | 
				
			||||||
import io.ktor.client.engine.HttpClientEngine
 | 
					import io.ktor.client.engine.HttpClientEngine
 | 
				
			||||||
import io.ktor.client.engine.okhttp.OkHttp
 | 
					import io.ktor.client.engine.okhttp.OkHttp
 | 
				
			||||||
import io.ktor.util.cio.toByteArray
 | 
					import io.ktor.util.cio.toByteArray
 | 
				
			||||||
 | 
					import kotlinx.coroutines.delay
 | 
				
			||||||
import kotlinx.io.charsets.Charset
 | 
					import kotlinx.io.charsets.Charset
 | 
				
			||||||
import kotlinx.serialization.json.JSON
 | 
					import kotlinx.serialization.json.JSON
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -22,7 +24,8 @@ class KtorRequestsExecutor(
 | 
				
			|||||||
    hostUrl: String = "https://api.telegram.org",
 | 
					    hostUrl: String = "https://api.telegram.org",
 | 
				
			||||||
    callsFactories: List<KtorCallFactory> = emptyList(),
 | 
					    callsFactories: List<KtorCallFactory> = emptyList(),
 | 
				
			||||||
    excludeDefaultFactories: Boolean = false,
 | 
					    excludeDefaultFactories: Boolean = false,
 | 
				
			||||||
    private val requestsLimiter: RequestLimiter = EmptyLimiter
 | 
					    private val requestsLimiter: RequestLimiter = EmptyLimiter,
 | 
				
			||||||
 | 
					    private val jsonFormatter: JSON = JSON.nonstrict
 | 
				
			||||||
) : BaseRequestsExecutor(token, hostUrl) {
 | 
					) : BaseRequestsExecutor(token, hostUrl) {
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        token: String,
 | 
					        token: String,
 | 
				
			||||||
@@ -59,11 +62,19 @@ class KtorRequestsExecutor(
 | 
				
			|||||||
                throw IllegalArgumentException("Can't execute request: $request")
 | 
					                throw IllegalArgumentException("Can't execute request: $request")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val content = call.response.content.toByteArray().toString(Charset.defaultCharset())
 | 
					            val content = call.response.content.toByteArray().toString(Charset.defaultCharset())
 | 
				
			||||||
            val responseObject = JSON.parse(
 | 
					            val responseObject = jsonFormatter.parse(
 | 
				
			||||||
                ResponseParameters.serializer(request.resultSerializer()),
 | 
					                Response.serializer(request.resultSerializer()),
 | 
				
			||||||
                content
 | 
					                content
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            responseObject.result ?: call.let {
 | 
					            responseObject.result ?: responseObject.parameters ?.let {
 | 
				
			||||||
 | 
					                val error = it.error
 | 
				
			||||||
 | 
					                if (error is RetryAfterError) {
 | 
				
			||||||
 | 
					                    delay(error.leftToRetry)
 | 
				
			||||||
 | 
					                    execute(request)
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    null
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } ?: call.let {
 | 
				
			||||||
                throw RequestException(
 | 
					                throw RequestException(
 | 
				
			||||||
                    responseObject,
 | 
					                    responseObject,
 | 
				
			||||||
                    "Can't get result object"
 | 
					                    "Can't get result object"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
package com.github.insanusmokrassar.TelegramBotAPI.bot
 | 
					package com.github.insanusmokrassar.TelegramBotAPI.bot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ResponseParameters
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.Response
 | 
				
			||||||
import java.io.IOException
 | 
					import java.io.IOException
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RequestException(
 | 
					class RequestException(
 | 
				
			||||||
    val response: ResponseParameters<*>,
 | 
					    val response: Response<*>,
 | 
				
			||||||
    message: String? = null,
 | 
					    message: String? = null,
 | 
				
			||||||
    cause: Throwable? = null
 | 
					    cause: Throwable? = null
 | 
				
			||||||
) : IOException(
 | 
					) : IOException(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
package com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts
 | 
					package com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ResponseParameters
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.Response
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
 | 
				
			||||||
import kotlinx.serialization.*
 | 
					import kotlinx.serialization.*
 | 
				
			||||||
import kotlinx.serialization.json.JsonObject
 | 
					import kotlinx.serialization.json.JsonObject
 | 
				
			||||||
@@ -15,6 +15,6 @@ interface Request<T: Any> {
 | 
				
			|||||||
fun <T : Any> StringFormat.extractResult(
 | 
					fun <T : Any> StringFormat.extractResult(
 | 
				
			||||||
    from: String,
 | 
					    from: String,
 | 
				
			||||||
    dataSerializer: KSerializer<T>
 | 
					    dataSerializer: KSerializer<T>
 | 
				
			||||||
): ResponseParameters<T> {
 | 
					): Response<T> {
 | 
				
			||||||
    return parse(ResponseParameters.serializer(dataSerializer), from)
 | 
					    return parse(Response.serializer(dataSerializer), from)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package com.github.insanusmokrassar.TelegramBotAPI.types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeUnit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sealed class RequestError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data class RetryAfterError(
 | 
				
			||||||
 | 
					    val seconds: Long,
 | 
				
			||||||
 | 
					    val startCountingMillis: Long
 | 
				
			||||||
 | 
					) : RequestError() {
 | 
				
			||||||
 | 
					    val canContinue = TimeUnit.SECONDS.toMillis(seconds) + startCountingMillis
 | 
				
			||||||
 | 
					    val leftToRetry: Long
 | 
				
			||||||
 | 
					        get() = canContinue - System.currentTimeMillis()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data class MigrateChatId(
 | 
				
			||||||
 | 
					    val newChatId: ChatId
 | 
				
			||||||
 | 
					) : RequestError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package com.github.insanusmokrassar.TelegramBotAPI.types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.serialization.*
 | 
				
			||||||
 | 
					import org.joda.time.DateTime
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeUnit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Deprecated(
 | 
				
			||||||
 | 
					    "Deprecated because incorrect name",
 | 
				
			||||||
 | 
					    ReplaceWith("Response")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					typealias ResponseParameters<T> = Response<T>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Serializable
 | 
				
			||||||
 | 
					data class Response<T : Any>(
 | 
				
			||||||
 | 
					    val ok: Boolean = false,
 | 
				
			||||||
 | 
					    @Optional
 | 
				
			||||||
 | 
					    val description: String? = null,
 | 
				
			||||||
 | 
					    @SerialName("error_code")
 | 
				
			||||||
 | 
					    @Optional
 | 
				
			||||||
 | 
					    val errorCode: Int? = null,
 | 
				
			||||||
 | 
					    @Optional
 | 
				
			||||||
 | 
					    val result: T? = null,
 | 
				
			||||||
 | 
					    @Optional
 | 
				
			||||||
 | 
					    val parameters: ResponseParametersRaw? = null
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import kotlinx.serialization.*
 | 
					 | 
				
			||||||
import org.joda.time.DateTime
 | 
					 | 
				
			||||||
import java.util.concurrent.TimeUnit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Serializable
 | 
					 | 
				
			||||||
data class ResponseParameters<T : Any>(
 | 
					 | 
				
			||||||
    val ok: Boolean = false,
 | 
					 | 
				
			||||||
    @Optional
 | 
					 | 
				
			||||||
    val description: String? = null,
 | 
					 | 
				
			||||||
    @SerialName("migrate_to_chat_id")
 | 
					 | 
				
			||||||
    @Optional
 | 
					 | 
				
			||||||
    val migrateToChatId: Identifier? = null,
 | 
					 | 
				
			||||||
    @SerialName("retry_after")
 | 
					 | 
				
			||||||
    @Optional
 | 
					 | 
				
			||||||
    val retryAfter: Int? = null,
 | 
					 | 
				
			||||||
    @SerialName("error_code")
 | 
					 | 
				
			||||||
    @Optional
 | 
					 | 
				
			||||||
    val errorCode: Int? = null,
 | 
					 | 
				
			||||||
    @Optional
 | 
					 | 
				
			||||||
    val result: T? = null
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    @Transient
 | 
					 | 
				
			||||||
    val waitUntil: DateTime? by lazy {
 | 
					 | 
				
			||||||
        retryAfter ?.let {
 | 
					 | 
				
			||||||
            DateTime.now().plus(TimeUnit.SECONDS.toMillis(it.toLong()))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package com.github.insanusmokrassar.TelegramBotAPI.types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.serialization.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Serializable
 | 
				
			||||||
 | 
					data class ResponseParametersRaw(
 | 
				
			||||||
 | 
					    @SerialName("migrate_to_chat_id")
 | 
				
			||||||
 | 
					    @Optional
 | 
				
			||||||
 | 
					    private val migrateToChatId: ChatId? = null,
 | 
				
			||||||
 | 
					    @SerialName("retry_after")
 | 
				
			||||||
 | 
					    @Optional
 | 
				
			||||||
 | 
					    private val retryAfter: Long? = null
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    @Transient
 | 
				
			||||||
 | 
					    private val createTime: Long = System.currentTimeMillis()
 | 
				
			||||||
 | 
					    @Transient
 | 
				
			||||||
 | 
					    val error: RequestError? by lazy {
 | 
				
			||||||
 | 
					        when {
 | 
				
			||||||
 | 
					            migrateToChatId != null -> MigrateChatId(migrateToChatId);
 | 
				
			||||||
 | 
					            retryAfter != null -> RetryAfterError(retryAfter, createTime);
 | 
				
			||||||
 | 
					            else -> null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,7 +4,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestException
 | 
				
			|||||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.*
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.requests.*
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ResponseParameters
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.Response
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
 | 
				
			||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
 | 
					import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
 | 
				
			||||||
@@ -147,7 +147,7 @@ fun RequestsExecutor.startGettingOfUpdates(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
fun <T: Any> RequestsExecutor.executeAsync(
 | 
					fun <T: Any> RequestsExecutor.executeAsync(
 | 
				
			||||||
    request: Request<T>,
 | 
					    request: Request<T>,
 | 
				
			||||||
    onFail: (suspend (ResponseParameters<*>) -> Unit)? = null,
 | 
					    onFail: (suspend (Response<*>) -> Unit)? = null,
 | 
				
			||||||
    scope: CoroutineScope = GlobalScope,
 | 
					    scope: CoroutineScope = GlobalScope,
 | 
				
			||||||
    onSuccess: (suspend (T) -> Unit)? = null
 | 
					    onSuccess: (suspend (T) -> Unit)? = null
 | 
				
			||||||
): Job {
 | 
					): Job {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user