mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-29 13:38:43 +00:00
commit
13d02afe6a
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,5 +1,17 @@
|
|||||||
# TelegramBotAPI changelog
|
# TelegramBotAPI changelog
|
||||||
|
|
||||||
|
## 0.15.0
|
||||||
|
|
||||||
|
* Old `UpdatesPoller` removed (was deprecated)
|
||||||
|
* `UpdatesPoller` renamed to `KtorUpdatesPoller`
|
||||||
|
* Now `KtorUpdatesPoller` do not use additional delay between requests and await answer from Telegram all timeout time
|
||||||
|
* Added abstraction `UpdatesPoller`
|
||||||
|
* Changed signature of the most count of `startGettingOfUpdates`:
|
||||||
|
* They are not `suspend` for now
|
||||||
|
* They are return `UpdatesPoller`
|
||||||
|
* They are using `timeoutMillis` instead of `requestsDelayMillis`
|
||||||
|
* Added `CIO` ktor client engine as lightweight default engine for long-polling
|
||||||
|
|
||||||
## 0.14.0
|
## 0.14.0
|
||||||
|
|
||||||
* Now library have no default engine for both webhooks and requests executor. It is required for clients to set
|
* Now library have no default engine for both webhooks and requests executor. It is required for clients to set
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
project.version = "0.14.2"
|
project.version = "0.15.0"
|
||||||
project.group = "com.github.insanusmokrassar"
|
project.group = "com.github.insanusmokrassar"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
@ -35,6 +35,7 @@ dependencies {
|
|||||||
implementation "joda-time:joda-time:$joda_time_version"
|
implementation "joda-time:joda-time:$joda_time_version"
|
||||||
|
|
||||||
implementation "io.ktor:ktor-client:$ktor_version"
|
implementation "io.ktor:ktor-client:$ktor_version"
|
||||||
|
implementation "io.ktor:ktor-client-cio:$ktor_version"
|
||||||
|
|
||||||
implementation "io.ktor:ktor-server:$ktor_version"
|
implementation "io.ktor:ktor-server:$ktor_version"
|
||||||
implementation "io.ktor:ktor-server-host-common:$ktor_version"
|
implementation "io.ktor:ktor-server-host-common:$ktor_version"
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.bot
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.io.core.Closeable
|
||||||
|
|
||||||
|
interface UpdatesPoller : Closeable {
|
||||||
|
fun start(scope: CoroutineScope = CoroutineScope(Dispatchers.Default))
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers
|
package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorRequestsExecutor
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.UpdatesPoller
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.GetUpdates
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.GetUpdates
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.DeleteWebhook
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.DeleteWebhook
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ALL_UPDATES_LIST
|
||||||
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.abstracts.BaseMessageUpdate
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate
|
||||||
@ -10,23 +13,58 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.UpdateReceiver
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.UpdateReceiver
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.executeUnsafe
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.executeUnsafe
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.cio.CIO
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
class UpdatesPoller(
|
fun KtorUpdatesPoller(
|
||||||
|
token: String,
|
||||||
|
timeoutSeconds: Int? = null,
|
||||||
|
oneTimeUpdatesLimit: Int? = null,
|
||||||
|
allowedUpdates: List<String> = ALL_UPDATES_LIST,
|
||||||
|
exceptionsHandler: (Exception) -> Boolean = { true },
|
||||||
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
|
): KtorUpdatesPoller {
|
||||||
|
val executor = KtorRequestsExecutor(
|
||||||
|
token,
|
||||||
|
HttpClient(
|
||||||
|
CIO.create {
|
||||||
|
timeoutSeconds ?.let { _ ->
|
||||||
|
val timeout = timeoutSeconds.toLong() * 1000
|
||||||
|
endpoint.apply {
|
||||||
|
keepAliveTime = timeout
|
||||||
|
connectTimeout = 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return KtorUpdatesPoller(
|
||||||
|
executor,
|
||||||
|
timeoutSeconds,
|
||||||
|
oneTimeUpdatesLimit,
|
||||||
|
allowedUpdates,
|
||||||
|
exceptionsHandler,
|
||||||
|
updatesReceiver
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KtorUpdatesPoller(
|
||||||
private val executor: RequestsExecutor,
|
private val executor: RequestsExecutor,
|
||||||
private val requestsDelayMillis: Long = 1000,
|
private val timeoutSeconds: Int? = null,
|
||||||
private val scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
private val oneTimeUpdatesLimit: Int? = null,
|
||||||
private val allowedUpdates: List<String>? = null,
|
private val allowedUpdates: List<String> = ALL_UPDATES_LIST,
|
||||||
private val block: UpdateReceiver<Update>
|
private val exceptionsHandler: (Exception) -> Boolean = { it.printStackTrace(); true },
|
||||||
) {
|
private val updatesReceiver: UpdateReceiver<Update>
|
||||||
|
) : UpdatesPoller {
|
||||||
private var lastHandledUpdate: UpdateIdentifier = 0L
|
private var lastHandledUpdate: UpdateIdentifier = 0L
|
||||||
private val mediaGroup: MutableList<BaseMessageUpdate> = mutableListOf()
|
private val mediaGroup: MutableList<BaseMessageUpdate> = mutableListOf()
|
||||||
|
|
||||||
private var pollerJob: Job? = null
|
private var pollerJob: Job? = null
|
||||||
|
|
||||||
private suspend fun sendToBlock(data: Update) {
|
private suspend fun sendToBlock(data: Update) {
|
||||||
block(data)
|
updatesReceiver(data)
|
||||||
lastHandledUpdate = data.updateId
|
lastHandledUpdate = data.updateId
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +86,9 @@ class UpdatesPoller(
|
|||||||
return executor.execute(
|
return executor.execute(
|
||||||
GetUpdates(
|
GetUpdates(
|
||||||
lastHandledUpdate + 1, // incremented because offset counted from 1 when updates id from 0
|
lastHandledUpdate + 1, // incremented because offset counted from 1 when updates id from 0
|
||||||
allowed_updates = allowedUpdates
|
oneTimeUpdatesLimit,
|
||||||
|
timeoutSeconds,
|
||||||
|
allowedUpdates
|
||||||
)
|
)
|
||||||
).map {
|
).map {
|
||||||
it.asUpdate
|
it.asUpdate
|
||||||
@ -72,16 +112,21 @@ class UpdatesPoller(
|
|||||||
pushMediaGroupUpdate()
|
pushMediaGroupUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun start(): Job {
|
@Synchronized
|
||||||
executor.executeUnsafe(DeleteWebhook())
|
override fun start(scope: CoroutineScope) {
|
||||||
return pollerJob ?: scope.launch {
|
pollerJob ?: scope.launch {
|
||||||
|
executor.executeUnsafe(DeleteWebhook())
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
delay(requestsDelayMillis)
|
|
||||||
try {
|
try {
|
||||||
val updates = getUpdates()
|
val updates = getUpdates()
|
||||||
handleUpdates(updates)
|
handleUpdates(updates)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
if (exceptionsHandler(e)) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
close()
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
@ -89,7 +134,8 @@ class UpdatesPoller(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun stop() {
|
@Synchronized
|
||||||
pollerJob ?.cancelAndJoin()
|
override fun close() {
|
||||||
|
pollerJob ?.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions
|
|
||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller
|
|
||||||
|
|
||||||
@Deprecated(
|
|
||||||
"Replaced in separated package",
|
|
||||||
ReplaceWith(
|
|
||||||
"UpdatesPoller",
|
|
||||||
"com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
typealias UpdatesPoller = UpdatesPoller
|
|
@ -1,26 +1,35 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions
|
package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions
|
||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.UpdatesPoller
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ALL_UPDATES_LIST
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.KtorUpdatesPoller
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
typealias UpdateReceiver<T> = suspend (T) -> Unit
|
typealias UpdateReceiver<T> = suspend (T) -> Unit
|
||||||
|
|
||||||
suspend fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
requestsDelayMillis: Long = 1000,
|
timeoutMillis: Long = 30 * 1000,
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
block: UpdateReceiver<Update>
|
block: UpdateReceiver<Update>
|
||||||
): Job {
|
): UpdatesPoller {
|
||||||
return UpdatesPoller(this, requestsDelayMillis, scope, allowedUpdates, block).start()
|
return KtorUpdatesPoller(
|
||||||
|
this,
|
||||||
|
timeoutMillis.toInt() / 1000,
|
||||||
|
allowedUpdates = allowedUpdates ?: ALL_UPDATES_LIST,
|
||||||
|
updatesReceiver = block
|
||||||
|
).also {
|
||||||
|
it.start(scope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
||||||
messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null,
|
messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null,
|
||||||
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
|
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
|
||||||
@ -35,9 +44,9 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
|
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
|
||||||
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
|
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
|
||||||
pollCallback: UpdateReceiver<PollUpdate>? = null,
|
pollCallback: UpdateReceiver<PollUpdate>? = null,
|
||||||
requestsDelayMillis: Long = 1000,
|
timeoutMillis: Long = 30 * 1000,
|
||||||
scope: CoroutineScope = GlobalScope
|
scope: CoroutineScope = GlobalScope
|
||||||
): Job {
|
): UpdatesPoller {
|
||||||
val filter = UpdatesFilter(
|
val filter = UpdatesFilter(
|
||||||
messageCallback,
|
messageCallback,
|
||||||
messageMediaGroupCallback,
|
messageMediaGroupCallback,
|
||||||
@ -55,14 +64,14 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
pollCallback
|
pollCallback
|
||||||
)
|
)
|
||||||
return startGettingOfUpdates(
|
return startGettingOfUpdates(
|
||||||
requestsDelayMillis,
|
timeoutMillis,
|
||||||
scope,
|
scope,
|
||||||
filter.allowedUpdates,
|
filter.allowedUpdates,
|
||||||
filter.asUpdateReceiver
|
filter.asUpdateReceiver
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
||||||
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
|
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
|
||||||
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
|
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
|
||||||
@ -74,9 +83,9 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
|
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
|
||||||
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
|
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
|
||||||
pollCallback: UpdateReceiver<PollUpdate>? = null,
|
pollCallback: UpdateReceiver<PollUpdate>? = null,
|
||||||
requestsDelayMillis: Long = 1000,
|
timeoutMillis: Long = 30 * 1000,
|
||||||
scope: CoroutineScope = GlobalScope
|
scope: CoroutineScope = GlobalScope
|
||||||
): Job = startGettingOfUpdates(
|
): UpdatesPoller = startGettingOfUpdates(
|
||||||
messageCallback = messageCallback,
|
messageCallback = messageCallback,
|
||||||
messageMediaGroupCallback = mediaGroupCallback,
|
messageMediaGroupCallback = mediaGroupCallback,
|
||||||
editedMessageCallback = editedMessageCallback,
|
editedMessageCallback = editedMessageCallback,
|
||||||
@ -91,6 +100,6 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
shippingQueryCallback = shippingQueryCallback,
|
shippingQueryCallback = shippingQueryCallback,
|
||||||
preCheckoutQueryCallback = preCheckoutQueryCallback,
|
preCheckoutQueryCallback = preCheckoutQueryCallback,
|
||||||
pollCallback = pollCallback,
|
pollCallback = pollCallback,
|
||||||
requestsDelayMillis = requestsDelayMillis,
|
timeoutMillis = timeoutMillis,
|
||||||
scope = scope
|
scope = scope
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user