diff --git a/CHANGELOG.md b/CHANGELOG.md index 52759d01f1..a71af3dd13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,14 @@ some default library * `ForwardedFromChannelMessage` - for messages from channels * Changed logic of forwarded messages preparing +### 0.14.1 + +* Replace `UpdatesFilter` and `UpdatesPoller` into another package +* Replace `WebhookPrivateKeyConfig` +* Added `FlowsUpdatesFilter` +* `UpdatesFilter` now have additional callback for polls +* `StopPoll#replyMarkup` now is optional + ## 0.13.0 Telegram Polls * Type `PollOption` and `AnonymousPollOption` added diff --git a/build.gradle b/build.gradle index a7ed40969e..75bf10f8a9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -project.version = "0.14.0" +project.version = "0.14.1" project.group = "com.github.insanusmokrassar" buildscript { diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/KtorRequestsExecutor.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/KtorRequestsExecutor.kt index cc4e3a2643..958b1bd33d 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/KtorRequestsExecutor.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/KtorRequestsExecutor.kt @@ -14,7 +14,6 @@ import io.ktor.client.call.HttpClientCall import io.ktor.client.engine.HttpClientEngine import io.ktor.util.cio.toByteArray import kotlinx.coroutines.delay -import kotlinx.io.charsets.Charset import kotlinx.serialization.json.Json class KtorRequestsExecutor( diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/base/MultipartRequestCallFactory.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/base/MultipartRequestCallFactory.kt index 2f2e1015f0..c90ba16e95 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/base/MultipartRequestCallFactory.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/bot/Ktor/base/MultipartRequestCallFactory.kt @@ -5,7 +5,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.utils.mapWithCommonValues import io.ktor.client.HttpClient import io.ktor.client.request.forms.MultiPartFormDataContent import io.ktor.client.request.forms.formData -import io.ktor.http.* +import io.ktor.http.Headers +import io.ktor.http.HttpHeaders class MultipartRequestCallFactory : AbstractRequestCallFactory() { diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/GetUpdates.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/GetUpdates.kt index b5f88f9882..3c697c3a7d 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/GetUpdates.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/GetUpdates.kt @@ -26,6 +26,8 @@ const val UPDATE_CALLBACK_QUERY = com.github.insanusmokrassar.TelegramBotAPI.typ const val UPDATE_SHIPPING_QUERY = com.github.insanusmokrassar.TelegramBotAPI.types.UPDATE_SHIPPING_QUERY @Deprecated("Replaced to other package", ReplaceWith("UPDATE_PRE_CHECKOUT_QUERY", "com.github.insanusmokrassar.TelegramBotAPI.types.UPDATE_PRE_CHECKOUT_QUERY")) const val UPDATE_PRE_CHECKOUT_QUERY = com.github.insanusmokrassar.TelegramBotAPI.types.UPDATE_PRE_CHECKOUT_QUERY +@Deprecated("Replaced to other package", ReplaceWith("UPDATE_POLL", "com.github.insanusmokrassar.TelegramBotAPI.types.UPDATE_POLL")) +const val UPDATE_POLL = com.github.insanusmokrassar.TelegramBotAPI.types.UPDATE_POLL @Serializable data class GetUpdates( diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/StopPoll.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/StopPoll.kt index 8f5a4118f0..f5327fa719 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/StopPoll.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/StopPoll.kt @@ -15,7 +15,7 @@ data class StopPoll( @SerialName(messageIdField) override val messageId: MessageIdentifier, @SerialName(replyMarkupField) - override val replyMarkup: InlineKeyboardMarkup? + override val replyMarkup: InlineKeyboardMarkup? = null ) : MessageAction, SimpleRequest, ReplyMarkup { override fun method(): String = "stopPoll" override fun resultSerializer(): KSerializer = Poll.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendPoll.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendPoll.kt index 8a9eee0b57..347a2b7bd9 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendPoll.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendPoll.kt @@ -5,9 +5,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.send.abstracts.SendMe import com.github.insanusmokrassar.TelegramBotAPI.types.* import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup import com.github.insanusmokrassar.TelegramBotAPI.types.message.RawMessage -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable +import kotlinx.serialization.* @Serializable data class SendPoll( diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/UpdateTypes.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/UpdateTypes.kt index e5d477db3f..a24e00d4eb 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/UpdateTypes.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/UpdateTypes.kt @@ -9,6 +9,7 @@ const val UPDATE_INLINE_QUERY = "inline_query" const val UPDATE_CALLBACK_QUERY = "callback_query" const val UPDATE_SHIPPING_QUERY = "shipping_query" const val UPDATE_PRE_CHECKOUT_QUERY = "pre_checkout_query" +const val UPDATE_POLL = "poll" val ALL_UPDATES_LIST = listOf( UPDATE_MESSAGE, @@ -19,5 +20,6 @@ val ALL_UPDATES_LIST = listOf( UPDATE_INLINE_QUERY, UPDATE_CALLBACK_QUERY, UPDATE_SHIPPING_QUERY, - UPDATE_PRE_CHECKOUT_QUERY + UPDATE_PRE_CHECKOUT_QUERY, + UPDATE_POLL ) diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/InlineKeyboardMarkup.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/InlineKeyboardMarkup.kt index a5ff3ee61e..64d3490c59 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/InlineKeyboardMarkup.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/InlineKeyboardMarkup.kt @@ -2,8 +2,8 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.buttons import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardButtons.InlineKeyboardButton import com.github.insanusmokrassar.TelegramBotAPI.types.inlineKeyboardField -import kotlinx.serialization.* -import kotlinx.serialization.internal.ArrayListSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable @Serializable data class InlineKeyboardMarkup( diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/FlowsUpdatesFilter.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/FlowsUpdatesFilter.kt new file mode 100644 index 0000000000..6efc1d9abf --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/FlowsUpdatesFilter.kt @@ -0,0 +1,60 @@ +package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers + +import com.github.insanusmokrassar.TelegramBotAPI.types.update.* +import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.* +import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.UpdateReceiver +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.asFlow + +private fun BroadcastChannel.createUpdateReceiver(): UpdateReceiver = ::send + +class FlowsUpdatesFilter { + private val messageChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val messageMediaGroupChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val editedMessageChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val editedMessageMediaGroupChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val channelPostChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val channelPostMediaGroupChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val editedChannelPostChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val editedChannelPostMediaGroupChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val chosenInlineResultChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val inlineQueryChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val callbackQueryChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val shippingQueryChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val preCheckoutQueryChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + private val pollChannel: BroadcastChannel = BroadcastChannel(Channel.CONFLATED) + + val filter = UpdatesFilter( + messageChannel.createUpdateReceiver(), + messageMediaGroupChannel.createUpdateReceiver(), + editedMessageChannel.createUpdateReceiver(), + editedMessageMediaGroupChannel.createUpdateReceiver(), + channelPostChannel.createUpdateReceiver(), + channelPostMediaGroupChannel.createUpdateReceiver(), + editedChannelPostChannel.createUpdateReceiver(), + editedChannelPostMediaGroupChannel.createUpdateReceiver(), + chosenInlineResultChannel.createUpdateReceiver(), + inlineQueryChannel.createUpdateReceiver(), + callbackQueryChannel.createUpdateReceiver(), + shippingQueryChannel.createUpdateReceiver(), + preCheckoutQueryChannel.createUpdateReceiver(), + pollChannel.createUpdateReceiver() + ) + + val messageFlow: Flow = messageChannel.asFlow() + val messageMediaGroupFlow: Flow = messageMediaGroupChannel.asFlow() + val editedMessageFlow: Flow = editedMessageChannel.asFlow() + val editedMessageMediaGroupFlow: Flow = editedMessageMediaGroupChannel.asFlow() + val channelPostFlow: Flow = channelPostChannel.asFlow() + val channelPostMediaGroupFlow: Flow = channelPostMediaGroupChannel.asFlow() + val editedChannelPostFlow: Flow = editedChannelPostChannel.asFlow() + val editedChannelPostMediaGroupFlow: Flow = editedChannelPostMediaGroupChannel.asFlow() + val chosenInlineResultFlow: Flow = chosenInlineResultChannel.asFlow() + val inlineQueryFlow: Flow = inlineQueryChannel.asFlow() + val callbackQueryFlow: Flow = callbackQueryChannel.asFlow() + val shippingQueryFlow: Flow = shippingQueryChannel.asFlow() + val preCheckoutQueryFlow: Flow = preCheckoutQueryChannel.asFlow() + val pollFlow: Flow = pollChannel.asFlow() +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesFilter.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesFilter.kt new file mode 100644 index 0000000000..218ec5737b --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesFilter.kt @@ -0,0 +1,110 @@ +package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers + +import com.github.insanusmokrassar.TelegramBotAPI.types.* +import com.github.insanusmokrassar.TelegramBotAPI.types.update.* +import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.* +import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update +import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.UpdateReceiver + +data class UpdatesFilter( + private val messageCallback: UpdateReceiver? = null, + private val messageMediaGroupCallback: UpdateReceiver? = null, + private val editedMessageCallback: UpdateReceiver? = null, + private val editedMessageMediaGroupCallback: UpdateReceiver? = null, + private val channelPostCallback: UpdateReceiver? = null, + private val channelPostMediaGroupCallback: UpdateReceiver? = null, + private val editedChannelPostCallback: UpdateReceiver? = null, + private val editedChannelPostMediaGroupCallback: UpdateReceiver? = null, + private val chosenInlineResultCallback: UpdateReceiver? = null, + private val inlineQueryCallback: UpdateReceiver? = null, + private val callbackQueryCallback: UpdateReceiver? = null, + private val shippingQueryCallback: UpdateReceiver? = null, + private val preCheckoutQueryCallback: UpdateReceiver? = null, + private val pollUpdateCallback: UpdateReceiver? = null +) { + val asUpdateReceiver: UpdateReceiver = this::invoke + val allowedUpdates = listOfNotNull( + (messageCallback ?: messageMediaGroupCallback) ?.let { UPDATE_MESSAGE }, + (editedMessageCallback ?: editedMessageMediaGroupCallback) ?.let { UPDATE_EDITED_MESSAGE }, + (channelPostCallback ?: channelPostMediaGroupCallback) ?.let { UPDATE_CHANNEL_POST }, + (editedChannelPostCallback ?: editedChannelPostMediaGroupCallback) ?.let { UPDATE_EDITED_CHANNEL_POST }, + chosenInlineResultCallback ?.let { UPDATE_CHOSEN_INLINE_RESULT }, + inlineQueryCallback ?.let { UPDATE_INLINE_QUERY }, + callbackQueryCallback ?.let { UPDATE_CALLBACK_QUERY }, + shippingQueryCallback ?.let { UPDATE_SHIPPING_QUERY }, + preCheckoutQueryCallback ?.let { UPDATE_PRE_CHECKOUT_QUERY }, + pollUpdateCallback ?.let { UPDATE_POLL } + ) + + suspend fun invoke(update: Update) { + when (update) { + is MessageUpdate -> messageCallback ?.invoke(update) + is MessageMediaGroupUpdate -> messageMediaGroupCallback ?.also { receiver -> + receiver(update) + } ?: messageCallback ?.also { receiver -> + update.origins.mapNotNull { it as? MessageUpdate }.forEach { + receiver(it) + } + } + is EditMessageUpdate -> editedMessageCallback ?.invoke(update) + is EditMessageMediaGroupUpdate -> editedMessageMediaGroupCallback ?.also { receiver -> + receiver(update) + } ?: editedMessageCallback ?.also { receiver -> + update.origins.mapNotNull { it as? EditMessageUpdate }.forEach { + receiver(it) + } + } + is ChannelPostUpdate -> channelPostCallback ?.invoke(update) + is ChannelPostMediaGroupUpdate -> channelPostMediaGroupCallback ?.also { receiver -> + receiver(update) + } ?: channelPostCallback ?.also { receiver -> + update.origins.mapNotNull { it as? ChannelPostUpdate }.forEach { + receiver(it) + } + } + is EditChannelPostUpdate -> editedChannelPostCallback ?.invoke(update) + is EditChannelPostMediaGroupUpdate -> editedChannelPostMediaGroupCallback ?.also { receiver -> + receiver(update) + } ?: editedChannelPostCallback ?.also { receiver -> + update.origins.mapNotNull { it as? EditChannelPostUpdate }.forEach { + receiver(it) + } + } + is ChosenInlineResultUpdate -> chosenInlineResultCallback ?.invoke(update) + is InlineQueryUpdate -> inlineQueryCallback ?.invoke(update) + is CallbackQueryUpdate -> callbackQueryCallback ?.invoke(update) + is ShippingQueryUpdate -> shippingQueryCallback ?.invoke(update) + is PreCheckoutQueryUpdate -> preCheckoutQueryCallback ?.invoke(update) + is PollUpdate -> pollUpdateCallback ?.invoke(update) + } + } +} + +fun createSimpleUpdateFilter( + messageCallback: UpdateReceiver? = null, + mediaGroupCallback: UpdateReceiver? = null, + editedMessageCallback: UpdateReceiver? = null, + channelPostCallback: UpdateReceiver? = null, + editedChannelPostCallback: UpdateReceiver? = null, + chosenInlineResultCallback: UpdateReceiver? = null, + inlineQueryCallback: UpdateReceiver? = null, + callbackQueryCallback: UpdateReceiver? = null, + shippingQueryCallback: UpdateReceiver? = null, + preCheckoutQueryCallback: UpdateReceiver? = null, + pollCallback: UpdateReceiver? = null +): UpdatesFilter = UpdatesFilter( + messageCallback = messageCallback, + messageMediaGroupCallback = mediaGroupCallback, + editedMessageCallback = editedMessageCallback, + editedMessageMediaGroupCallback = mediaGroupCallback, + channelPostCallback = channelPostCallback, + channelPostMediaGroupCallback = mediaGroupCallback, + editedChannelPostCallback = editedChannelPostCallback, + editedChannelPostMediaGroupCallback = mediaGroupCallback, + chosenInlineResultCallback = chosenInlineResultCallback, + inlineQueryCallback = inlineQueryCallback, + callbackQueryCallback = callbackQueryCallback, + shippingQueryCallback = shippingQueryCallback, + preCheckoutQueryCallback = preCheckoutQueryCallback, + pollUpdateCallback = pollCallback +) diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesPoller.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesPoller.kt new file mode 100644 index 0000000000..672208d2ea --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesPoller.kt @@ -0,0 +1,98 @@ +package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers + +import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor +import com.github.insanusmokrassar.TelegramBotAPI.requests.GetUpdates +import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.DeleteWebhook +import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier +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.Update +import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.UpdateReceiver +import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.executeUnsafe +import com.github.insanusmokrassar.TelegramBotAPI.utils.mediaGroupId +import com.github.insanusmokrassar.TelegramBotAPI.utils.toMediaGroupUpdate +import kotlinx.coroutines.* +import java.util.concurrent.Executors + +class UpdatesPoller( + private val executor: RequestsExecutor, + private val requestsDelayMillis: Long = 1000, + private val scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()), + private val allowedUpdates: List? = null, + private val block: UpdateReceiver +) { + private var lastHandledUpdate: UpdateIdentifier = 0L + private val mediaGroup: MutableList = mutableListOf() + + private var pollerJob: Job? = null + + private suspend fun sendToBlock(data: Update) { + block(data) + lastHandledUpdate = data.updateId + } + + private suspend fun pushMediaGroupUpdate(update: BaseMessageUpdate? = null) { + val inputMediaGroupId = (update ?.data as? MediaGroupMessage) ?.mediaGroupId + if (mediaGroup.isNotEmpty() && inputMediaGroupId ?.equals(mediaGroup.mediaGroupId) != true) { + mediaGroup.sortBy { it.updateId } + mediaGroup.toMediaGroupUpdate() ?.let { + sendToBlock(it) + } ?: mediaGroup.forEach { + sendToBlock(it) + } + mediaGroup.clear() + } + inputMediaGroupId ?.let { + mediaGroup.add(update) + } ?: sendToBlock(update ?: return) + } + + private suspend fun getUpdates(): List { + return executor.execute( + GetUpdates( + lastHandledUpdate + 1, // incremented because offset counted from 1 when updates id from 0 + allowed_updates = allowedUpdates + ) + ).map { + it.asUpdate + } + } + + private suspend fun handleUpdates(updates: List) { + for (update in updates) { + (update as? BaseMessageUpdate) ?.let { + if (it.data is MediaGroupMessage) { + pushMediaGroupUpdate(it) + } else { + null + } + } ?:let { + pushMediaGroupUpdate() + sendToBlock(update) + } + } + + pushMediaGroupUpdate() + } + + suspend fun start(): Job { + executor.executeUnsafe(DeleteWebhook()) + return pollerJob ?: scope.launch { + while (isActive) { + delay(requestsDelayMillis) + try { + val updates = getUpdates() + handleUpdates(updates) + } catch (e: Exception) { + e.printStackTrace() + } + } + }.also { + pollerJob = it + } + } + + suspend fun stop() { + pollerJob ?.cancelAndJoin() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/webhook/WebhookPrivateKeyConfig.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/webhook/WebhookPrivateKeyConfig.kt new file mode 100644 index 0000000000..f6e6a7a1b0 --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/webhook/WebhookPrivateKeyConfig.kt @@ -0,0 +1,23 @@ +package com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook + +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import java.io.FileInputStream +import java.security.KeyStore + +@Serializable +data class WebhookPrivateKeyConfig( + private val keyStorePath: String, + private val keyStorePassword: String, + val aliasName: String, + private val aliasPassword: String +) { + @Transient + val keyStore = KeyStore.getInstance("JKS").apply { + load(FileInputStream(keyStorePath), keyStorePassword()) + } + + fun keyStorePassword(): CharArray = keyStorePassword.toCharArray() + + fun aliasPassword(): CharArray = aliasPassword.toCharArray() +} diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesFilter.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesFilter.kt index 4fcbdf807e..4538d225ad 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesFilter.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesFilter.kt @@ -1,81 +1,25 @@ package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions -import com.github.insanusmokrassar.TelegramBotAPI.types.* import com.github.insanusmokrassar.TelegramBotAPI.types.update.* -import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.* -import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update +import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.MediaGroupUpdate +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter -data class UpdatesFilter( - private val messageCallback: UpdateReceiver? = null, - private val messageMediaGroupCallback: UpdateReceiver? = null, - private val editedMessageCallback: UpdateReceiver? = null, - private val editedMessageMediaGroupCallback: UpdateReceiver? = null, - private val channelPostCallback: UpdateReceiver? = null, - private val channelPostMediaGroupCallback: UpdateReceiver? = null, - private val editedChannelPostCallback: UpdateReceiver? = null, - private val editedChannelPostMediaGroupCallback: UpdateReceiver? = null, - private val chosenInlineResultCallback: UpdateReceiver? = null, - private val inlineQueryCallback: UpdateReceiver? = null, - private val callbackQueryCallback: UpdateReceiver? = null, - private val shippingQueryCallback: UpdateReceiver? = null, - private val preCheckoutQueryCallback: UpdateReceiver? = null -) { - val asUpdateReceiver: UpdateReceiver = this::invoke - val allowedUpdates = listOfNotNull( - (messageCallback ?: messageMediaGroupCallback) ?.let { UPDATE_MESSAGE }, - (editedMessageCallback ?: editedMessageMediaGroupCallback) ?.let { UPDATE_EDITED_MESSAGE }, - (channelPostCallback ?: channelPostMediaGroupCallback) ?.let { UPDATE_CHANNEL_POST }, - (editedChannelPostCallback ?: editedChannelPostMediaGroupCallback) ?.let { UPDATE_EDITED_CHANNEL_POST }, - chosenInlineResultCallback ?.let { UPDATE_CHOSEN_INLINE_RESULT }, - inlineQueryCallback ?.let { UPDATE_INLINE_QUERY }, - callbackQueryCallback ?.let { UPDATE_CALLBACK_QUERY }, - shippingQueryCallback ?.let { UPDATE_SHIPPING_QUERY }, - preCheckoutQueryCallback ?.let { UPDATE_PRE_CHECKOUT_QUERY } +@Deprecated( + "Replaced in separated package", + ReplaceWith( + "UpdatesFilter", + "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter" ) +) +typealias UpdatesFilter = UpdatesFilter - suspend fun invoke(update: Update) { - when (update) { - is MessageUpdate -> messageCallback ?.invoke(update) - is MessageMediaGroupUpdate -> messageMediaGroupCallback ?.also { receiver -> - receiver(update) - } ?: messageCallback ?.also { receiver -> - update.origins.mapNotNull { it as? MessageUpdate }.forEach { - receiver(it) - } - } - is EditMessageUpdate -> editedMessageCallback ?.invoke(update) - is EditMessageMediaGroupUpdate -> editedMessageMediaGroupCallback ?.also { receiver -> - receiver(update) - } ?: editedMessageCallback ?.also { receiver -> - update.origins.mapNotNull { it as? EditMessageUpdate }.forEach { - receiver(it) - } - } - is ChannelPostUpdate -> channelPostCallback ?.invoke(update) - is ChannelPostMediaGroupUpdate -> channelPostMediaGroupCallback ?.also { receiver -> - receiver(update) - } ?: channelPostCallback ?.also { receiver -> - update.origins.mapNotNull { it as? ChannelPostUpdate }.forEach { - receiver(it) - } - } - is EditChannelPostUpdate -> editedChannelPostCallback ?.invoke(update) - is EditChannelPostMediaGroupUpdate -> editedChannelPostMediaGroupCallback ?.also { receiver -> - receiver(update) - } ?: editedChannelPostCallback ?.also { receiver -> - update.origins.mapNotNull { it as? EditChannelPostUpdate }.forEach { - receiver(it) - } - } - is ChosenInlineResultUpdate -> chosenInlineResultCallback ?.invoke(update) - is InlineQueryUpdate -> inlineQueryCallback ?.invoke(update) - is CallbackQueryUpdate -> callbackQueryCallback ?.invoke(update) - is ShippingQueryUpdate -> shippingQueryCallback ?.invoke(update) - is PreCheckoutQueryUpdate -> preCheckoutQueryCallback ?.invoke(update) - } - } -} - +@Deprecated( + "Replaced in separated package", + ReplaceWith( + "createSimpleUpdateFilter", + "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.createSimpleUpdateFilter" + ) +) fun createSimpleUpdateFilter( messageCallback: UpdateReceiver? = null, mediaGroupCallback: UpdateReceiver? = null, @@ -87,18 +31,15 @@ fun createSimpleUpdateFilter( callbackQueryCallback: UpdateReceiver? = null, shippingQueryCallback: UpdateReceiver? = null, preCheckoutQueryCallback: UpdateReceiver? = null -): UpdatesFilter = UpdatesFilter( - messageCallback = messageCallback, - messageMediaGroupCallback = mediaGroupCallback, - editedMessageCallback = editedMessageCallback, - editedMessageMediaGroupCallback = mediaGroupCallback, - channelPostCallback = channelPostCallback, - channelPostMediaGroupCallback = mediaGroupCallback, - editedChannelPostCallback = editedChannelPostCallback, - editedChannelPostMediaGroupCallback = mediaGroupCallback, - chosenInlineResultCallback = chosenInlineResultCallback, - inlineQueryCallback = inlineQueryCallback, - callbackQueryCallback = callbackQueryCallback, - shippingQueryCallback = shippingQueryCallback, - preCheckoutQueryCallback = preCheckoutQueryCallback +): UpdatesFilter = com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.createSimpleUpdateFilter( + messageCallback, + mediaGroupCallback, + editedMessageCallback, + channelPostCallback, + editedChannelPostCallback, + chosenInlineResultCallback, + inlineQueryCallback, + callbackQueryCallback, + shippingQueryCallback, + preCheckoutQueryCallback ) diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPoller.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPoller.kt index 7ead0ba33b..1d87bd6c17 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPoller.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPoller.kt @@ -1,96 +1,12 @@ package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions -import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor -import com.github.insanusmokrassar.TelegramBotAPI.requests.GetUpdates -import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.DeleteWebhook -import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier -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.Update -import com.github.insanusmokrassar.TelegramBotAPI.utils.mediaGroupId -import com.github.insanusmokrassar.TelegramBotAPI.utils.toMediaGroupUpdate -import kotlinx.coroutines.* -import java.util.concurrent.Executors +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller -class UpdatesPoller( - private val executor: RequestsExecutor, - private val requestsDelayMillis: Long = 1000, - private val scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()), - private val allowedUpdates: List? = null, - private val block: UpdateReceiver -) { - private var lastHandledUpdate: UpdateIdentifier = 0L - private val mediaGroup: MutableList = mutableListOf() - - private var pollerJob: Job? = null - - private suspend fun sendToBlock(data: Update) { - block(data) - lastHandledUpdate = data.updateId - } - - private suspend fun pushMediaGroupUpdate(update: BaseMessageUpdate? = null) { - val inputMediaGroupId = (update ?.data as? MediaGroupMessage) ?.mediaGroupId - if (mediaGroup.isNotEmpty() && inputMediaGroupId ?.equals(mediaGroup.mediaGroupId) != true) { - mediaGroup.sortBy { it.updateId } - mediaGroup.toMediaGroupUpdate() ?.let { - sendToBlock(it) - } ?: mediaGroup.forEach { - sendToBlock(it) - } - mediaGroup.clear() - } - inputMediaGroupId ?.let { - mediaGroup.add(update) - } ?: sendToBlock(update ?: return) - } - - private suspend fun getUpdates(): List { - return executor.execute( - GetUpdates( - lastHandledUpdate + 1, // incremented because offset counted from 1 when updates id from 0 - allowed_updates = allowedUpdates - ) - ).map { - it.asUpdate - } - } - - private suspend fun handleUpdates(updates: List) { - for (update in updates) { - (update as? BaseMessageUpdate) ?.let { - if (it.data is MediaGroupMessage) { - pushMediaGroupUpdate(it) - } else { - null - } - } ?:let { - pushMediaGroupUpdate() - sendToBlock(update) - } - } - - pushMediaGroupUpdate() - } - - suspend fun start(): Job { - executor.executeUnsafe(DeleteWebhook()) - return pollerJob ?: scope.launch { - while (isActive) { - delay(requestsDelayMillis) - try { - val updates = getUpdates() - handleUpdates(updates) - } catch (e: Exception) { - e.printStackTrace() - } - } - }.also { - pollerJob = it - } - } - - suspend fun stop() { - pollerJob ?.cancelAndJoin() - } -} \ No newline at end of file +@Deprecated( + "Replaced in separated package", + ReplaceWith( + "UpdatesPoller", + "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller" + ) +) +typealias UpdatesPoller = UpdatesPoller diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPolling.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPolling.kt index 8777aec2f5..42b87eced1 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPolling.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/UpdatesPolling.kt @@ -4,6 +4,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor import com.github.insanusmokrassar.TelegramBotAPI.types.update.* import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.* import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller import kotlinx.coroutines.* import java.util.concurrent.Executors @@ -32,6 +34,7 @@ suspend fun RequestsExecutor.startGettingOfUpdates( callbackQueryCallback: UpdateReceiver? = null, shippingQueryCallback: UpdateReceiver? = null, preCheckoutQueryCallback: UpdateReceiver? = null, + pollCallback: UpdateReceiver? = null, requestsDelayMillis: Long = 1000, scope: CoroutineScope = GlobalScope ): Job { @@ -48,7 +51,8 @@ suspend fun RequestsExecutor.startGettingOfUpdates( inlineQueryCallback, callbackQueryCallback, shippingQueryCallback, - preCheckoutQueryCallback + preCheckoutQueryCallback, + pollCallback ) return startGettingOfUpdates( requestsDelayMillis, @@ -69,6 +73,7 @@ suspend fun RequestsExecutor.startGettingOfUpdates( callbackQueryCallback: UpdateReceiver? = null, shippingQueryCallback: UpdateReceiver? = null, preCheckoutQueryCallback: UpdateReceiver? = null, + pollCallback: UpdateReceiver? = null, requestsDelayMillis: Long = 1000, scope: CoroutineScope = GlobalScope ): Job = startGettingOfUpdates( @@ -85,6 +90,7 @@ suspend fun RequestsExecutor.startGettingOfUpdates( callbackQueryCallback = callbackQueryCallback, shippingQueryCallback = shippingQueryCallback, preCheckoutQueryCallback = preCheckoutQueryCallback, + pollCallback = pollCallback, requestsDelayMillis = requestsDelayMillis, scope = scope ) diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/WebhookPrivateKeyConfig.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/WebhookPrivateKeyConfig.kt index bb5f4810c4..9462b67e2b 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/WebhookPrivateKeyConfig.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/WebhookPrivateKeyConfig.kt @@ -1,23 +1,12 @@ package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions -import kotlinx.serialization.Serializable -import kotlinx.serialization.Transient -import java.io.FileInputStream -import java.security.KeyStore +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook.WebhookPrivateKeyConfig -@Serializable -data class WebhookPrivateKeyConfig( - private val keyStorePath: String, - private val keyStorePassword: String, - val aliasName: String, - private val aliasPassword: String -) { - @Transient - val keyStore = KeyStore.getInstance("JKS").apply { - load(FileInputStream(keyStorePath), keyStorePassword()) - } - - fun keyStorePassword(): CharArray = keyStorePassword.toCharArray() - - fun aliasPassword(): CharArray = aliasPassword.toCharArray() -} +@Deprecated( + "Replaced in separated package", + ReplaceWith( + "WebhookPrivateKeyConfig", + "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook.WebhookPrivateKeyConfig" + ) +) +typealias WebhookPrivateKeyConfig = WebhookPrivateKeyConfig diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/Webhooks.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/Webhooks.kt index c198a22872..af6804d443 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/Webhooks.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/extensions/Webhooks.kt @@ -8,8 +8,9 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaG import com.github.insanusmokrassar.TelegramBotAPI.types.update.RawUpdate import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter +import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook.WebhookPrivateKeyConfig import com.github.insanusmokrassar.TelegramBotAPI.utils.toMediaGroupUpdate -import io.ktor.application.Application import io.ktor.application.call import io.ktor.request.receiveText import io.ktor.response.respond