1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-22 08:13:47 +00:00

Merge pull request #35 from InsanusMokrassar/0.14.1

0.14.1
This commit is contained in:
InsanusMokrassar 2019-05-13 06:58:40 +08:00 committed by GitHub
commit 1e0bf9e66d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 365 additions and 211 deletions

View File

@ -18,6 +18,14 @@ some default library
* `ForwardedFromChannelMessage` - for messages from channels * `ForwardedFromChannelMessage` - for messages from channels
* Changed logic of forwarded messages preparing * 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 ## 0.13.0 Telegram Polls
* Type `PollOption` and `AnonymousPollOption` added * Type `PollOption` and `AnonymousPollOption` added

View File

@ -1,4 +1,4 @@
project.version = "0.14.0" project.version = "0.14.1"
project.group = "com.github.insanusmokrassar" project.group = "com.github.insanusmokrassar"
buildscript { buildscript {

View File

@ -14,7 +14,6 @@ import io.ktor.client.call.HttpClientCall
import io.ktor.client.engine.HttpClientEngine import io.ktor.client.engine.HttpClientEngine
import io.ktor.util.cio.toByteArray import io.ktor.util.cio.toByteArray
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.io.charsets.Charset
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
class KtorRequestsExecutor( class KtorRequestsExecutor(

View File

@ -5,7 +5,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.utils.mapWithCommonValues
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.forms.MultiPartFormDataContent import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData import io.ktor.client.request.forms.formData
import io.ktor.http.* import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
class MultipartRequestCallFactory : AbstractRequestCallFactory() { class MultipartRequestCallFactory : AbstractRequestCallFactory() {

View File

@ -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 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")) @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 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 @Serializable
data class GetUpdates( data class GetUpdates(

View File

@ -15,7 +15,7 @@ data class StopPoll(
@SerialName(messageIdField) @SerialName(messageIdField)
override val messageId: MessageIdentifier, override val messageId: MessageIdentifier,
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? override val replyMarkup: InlineKeyboardMarkup? = null
) : MessageAction, SimpleRequest<Poll>, ReplyMarkup { ) : MessageAction, SimpleRequest<Poll>, ReplyMarkup {
override fun method(): String = "stopPoll" override fun method(): String = "stopPoll"
override fun resultSerializer(): KSerializer<Poll> = Poll.serializer() override fun resultSerializer(): KSerializer<Poll> = Poll.serializer()

View File

@ -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.*
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
import com.github.insanusmokrassar.TelegramBotAPI.types.message.RawMessage import com.github.insanusmokrassar.TelegramBotAPI.types.message.RawMessage
import kotlinx.serialization.KSerializer import kotlinx.serialization.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable @Serializable
data class SendPoll( data class SendPoll(

View File

@ -9,6 +9,7 @@ const val UPDATE_INLINE_QUERY = "inline_query"
const val UPDATE_CALLBACK_QUERY = "callback_query" const val UPDATE_CALLBACK_QUERY = "callback_query"
const val UPDATE_SHIPPING_QUERY = "shipping_query" const val UPDATE_SHIPPING_QUERY = "shipping_query"
const val UPDATE_PRE_CHECKOUT_QUERY = "pre_checkout_query" const val UPDATE_PRE_CHECKOUT_QUERY = "pre_checkout_query"
const val UPDATE_POLL = "poll"
val ALL_UPDATES_LIST = listOf( val ALL_UPDATES_LIST = listOf(
UPDATE_MESSAGE, UPDATE_MESSAGE,
@ -19,5 +20,6 @@ val ALL_UPDATES_LIST = listOf(
UPDATE_INLINE_QUERY, UPDATE_INLINE_QUERY,
UPDATE_CALLBACK_QUERY, UPDATE_CALLBACK_QUERY,
UPDATE_SHIPPING_QUERY, UPDATE_SHIPPING_QUERY,
UPDATE_PRE_CHECKOUT_QUERY UPDATE_PRE_CHECKOUT_QUERY,
UPDATE_POLL
) )

View File

@ -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.buttons.InlineKeyboardButtons.InlineKeyboardButton
import com.github.insanusmokrassar.TelegramBotAPI.types.inlineKeyboardField import com.github.insanusmokrassar.TelegramBotAPI.types.inlineKeyboardField
import kotlinx.serialization.* import kotlinx.serialization.SerialName
import kotlinx.serialization.internal.ArrayListSerializer import kotlinx.serialization.Serializable
@Serializable @Serializable
data class InlineKeyboardMarkup( data class InlineKeyboardMarkup(

View File

@ -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 <T> BroadcastChannel<T>.createUpdateReceiver(): UpdateReceiver<T> = ::send
class FlowsUpdatesFilter {
private val messageChannel: BroadcastChannel<MessageUpdate> = BroadcastChannel(Channel.CONFLATED)
private val messageMediaGroupChannel: BroadcastChannel<MessageMediaGroupUpdate> = BroadcastChannel(Channel.CONFLATED)
private val editedMessageChannel: BroadcastChannel<EditMessageUpdate> = BroadcastChannel(Channel.CONFLATED)
private val editedMessageMediaGroupChannel: BroadcastChannel<EditMessageMediaGroupUpdate> = BroadcastChannel(Channel.CONFLATED)
private val channelPostChannel: BroadcastChannel<ChannelPostUpdate> = BroadcastChannel(Channel.CONFLATED)
private val channelPostMediaGroupChannel: BroadcastChannel<ChannelPostMediaGroupUpdate> = BroadcastChannel(Channel.CONFLATED)
private val editedChannelPostChannel: BroadcastChannel<EditChannelPostUpdate> = BroadcastChannel(Channel.CONFLATED)
private val editedChannelPostMediaGroupChannel: BroadcastChannel<EditChannelPostMediaGroupUpdate> = BroadcastChannel(Channel.CONFLATED)
private val chosenInlineResultChannel: BroadcastChannel<ChosenInlineResultUpdate> = BroadcastChannel(Channel.CONFLATED)
private val inlineQueryChannel: BroadcastChannel<InlineQueryUpdate> = BroadcastChannel(Channel.CONFLATED)
private val callbackQueryChannel: BroadcastChannel<CallbackQueryUpdate> = BroadcastChannel(Channel.CONFLATED)
private val shippingQueryChannel: BroadcastChannel<ShippingQueryUpdate> = BroadcastChannel(Channel.CONFLATED)
private val preCheckoutQueryChannel: BroadcastChannel<PreCheckoutQueryUpdate> = BroadcastChannel(Channel.CONFLATED)
private val pollChannel: BroadcastChannel<PollUpdate> = 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<MessageUpdate> = messageChannel.asFlow()
val messageMediaGroupFlow: Flow<MessageMediaGroupUpdate> = messageMediaGroupChannel.asFlow()
val editedMessageFlow: Flow<EditMessageUpdate> = editedMessageChannel.asFlow()
val editedMessageMediaGroupFlow: Flow<EditMessageMediaGroupUpdate> = editedMessageMediaGroupChannel.asFlow()
val channelPostFlow: Flow<ChannelPostUpdate> = channelPostChannel.asFlow()
val channelPostMediaGroupFlow: Flow<ChannelPostMediaGroupUpdate> = channelPostMediaGroupChannel.asFlow()
val editedChannelPostFlow: Flow<EditChannelPostUpdate> = editedChannelPostChannel.asFlow()
val editedChannelPostMediaGroupFlow: Flow<EditChannelPostMediaGroupUpdate> = editedChannelPostMediaGroupChannel.asFlow()
val chosenInlineResultFlow: Flow<ChosenInlineResultUpdate> = chosenInlineResultChannel.asFlow()
val inlineQueryFlow: Flow<InlineQueryUpdate> = inlineQueryChannel.asFlow()
val callbackQueryFlow: Flow<CallbackQueryUpdate> = callbackQueryChannel.asFlow()
val shippingQueryFlow: Flow<ShippingQueryUpdate> = shippingQueryChannel.asFlow()
val preCheckoutQueryFlow: Flow<PreCheckoutQueryUpdate> = preCheckoutQueryChannel.asFlow()
val pollFlow: Flow<PollUpdate> = pollChannel.asFlow()
}

View File

@ -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<MessageUpdate>? = null,
private val messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null,
private val editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
private val editedMessageMediaGroupCallback: UpdateReceiver<EditMessageMediaGroupUpdate>? = null,
private val channelPostCallback: UpdateReceiver<ChannelPostUpdate>? = null,
private val channelPostMediaGroupCallback: UpdateReceiver<ChannelPostMediaGroupUpdate>? = null,
private val editedChannelPostCallback: UpdateReceiver<EditChannelPostUpdate>? = null,
private val editedChannelPostMediaGroupCallback: UpdateReceiver<EditChannelPostMediaGroupUpdate>? = null,
private val chosenInlineResultCallback: UpdateReceiver<ChosenInlineResultUpdate>? = null,
private val inlineQueryCallback: UpdateReceiver<InlineQueryUpdate>? = null,
private val callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
private val shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
private val preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
private val pollUpdateCallback: UpdateReceiver<PollUpdate>? = null
) {
val asUpdateReceiver: UpdateReceiver<Update> = 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<MessageUpdate>? = null,
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
channelPostCallback: UpdateReceiver<ChannelPostUpdate>? = null,
editedChannelPostCallback: UpdateReceiver<EditChannelPostUpdate>? = null,
chosenInlineResultCallback: UpdateReceiver<ChosenInlineResultUpdate>? = null,
inlineQueryCallback: UpdateReceiver<InlineQueryUpdate>? = null,
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
pollCallback: UpdateReceiver<PollUpdate>? = 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
)

View File

@ -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<String>? = null,
private val block: UpdateReceiver<Update>
) {
private var lastHandledUpdate: UpdateIdentifier = 0L
private val mediaGroup: MutableList<BaseMessageUpdate> = 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<Update> {
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<Update>) {
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()
}
}

View File

@ -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()
}

View File

@ -1,81 +1,25 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions 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.*
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.* import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.MediaGroupUpdate
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter
data class UpdatesFilter( @Deprecated(
private val messageCallback: UpdateReceiver<MessageUpdate>? = null, "Replaced in separated package",
private val messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null, ReplaceWith(
private val editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null, "UpdatesFilter",
private val editedMessageMediaGroupCallback: UpdateReceiver<EditMessageMediaGroupUpdate>? = null, "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter"
private val channelPostCallback: UpdateReceiver<ChannelPostUpdate>? = null,
private val channelPostMediaGroupCallback: UpdateReceiver<ChannelPostMediaGroupUpdate>? = null,
private val editedChannelPostCallback: UpdateReceiver<EditChannelPostUpdate>? = null,
private val editedChannelPostMediaGroupCallback: UpdateReceiver<EditChannelPostMediaGroupUpdate>? = null,
private val chosenInlineResultCallback: UpdateReceiver<ChosenInlineResultUpdate>? = null,
private val inlineQueryCallback: UpdateReceiver<InlineQueryUpdate>? = null,
private val callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
private val shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
private val preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null
) {
val asUpdateReceiver: UpdateReceiver<Update> = 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 }
) )
)
typealias UpdatesFilter = UpdatesFilter
suspend fun invoke(update: Update) { @Deprecated(
when (update) { "Replaced in separated package",
is MessageUpdate -> messageCallback ?.invoke(update) ReplaceWith(
is MessageMediaGroupUpdate -> messageMediaGroupCallback ?.also { receiver -> "createSimpleUpdateFilter",
receiver(update) "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.createSimpleUpdateFilter"
} ?: 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)
}
}
}
fun createSimpleUpdateFilter( fun createSimpleUpdateFilter(
messageCallback: UpdateReceiver<MessageUpdate>? = null, messageCallback: UpdateReceiver<MessageUpdate>? = null,
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null, mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
@ -87,18 +31,15 @@ fun createSimpleUpdateFilter(
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null, callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null, shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null
): UpdatesFilter = UpdatesFilter( ): UpdatesFilter = com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.createSimpleUpdateFilter(
messageCallback = messageCallback, messageCallback,
messageMediaGroupCallback = mediaGroupCallback, mediaGroupCallback,
editedMessageCallback = editedMessageCallback, editedMessageCallback,
editedMessageMediaGroupCallback = mediaGroupCallback, channelPostCallback,
channelPostCallback = channelPostCallback, editedChannelPostCallback,
channelPostMediaGroupCallback = mediaGroupCallback, chosenInlineResultCallback,
editedChannelPostCallback = editedChannelPostCallback, inlineQueryCallback,
editedChannelPostMediaGroupCallback = mediaGroupCallback, callbackQueryCallback,
chosenInlineResultCallback = chosenInlineResultCallback, shippingQueryCallback,
inlineQueryCallback = inlineQueryCallback, preCheckoutQueryCallback
callbackQueryCallback = callbackQueryCallback,
shippingQueryCallback = shippingQueryCallback,
preCheckoutQueryCallback = preCheckoutQueryCallback
) )

View File

@ -1,96 +1,12 @@
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.updateshandlers.UpdatesPoller
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
class UpdatesPoller( @Deprecated(
private val executor: RequestsExecutor, "Replaced in separated package",
private val requestsDelayMillis: Long = 1000, ReplaceWith(
private val scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()), "UpdatesPoller",
private val allowedUpdates: List<String>? = null, "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesPoller"
private val block: UpdateReceiver<Update> )
) { )
private var lastHandledUpdate: UpdateIdentifier = 0L typealias UpdatesPoller = UpdatesPoller
private val mediaGroup: MutableList<BaseMessageUpdate> = 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<Update> {
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<Update>) {
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()
}
}

View File

@ -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.*
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.UpdatesPoller
import kotlinx.coroutines.* import kotlinx.coroutines.*
import java.util.concurrent.Executors import java.util.concurrent.Executors
@ -32,6 +34,7 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null, callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null, shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null, preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
pollCallback: UpdateReceiver<PollUpdate>? = null,
requestsDelayMillis: Long = 1000, requestsDelayMillis: Long = 1000,
scope: CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
): Job { ): Job {
@ -48,7 +51,8 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
inlineQueryCallback, inlineQueryCallback,
callbackQueryCallback, callbackQueryCallback,
shippingQueryCallback, shippingQueryCallback,
preCheckoutQueryCallback preCheckoutQueryCallback,
pollCallback
) )
return startGettingOfUpdates( return startGettingOfUpdates(
requestsDelayMillis, requestsDelayMillis,
@ -69,6 +73,7 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null, callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null, shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null, preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
pollCallback: UpdateReceiver<PollUpdate>? = null,
requestsDelayMillis: Long = 1000, requestsDelayMillis: Long = 1000,
scope: CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
): Job = startGettingOfUpdates( ): Job = startGettingOfUpdates(
@ -85,6 +90,7 @@ suspend fun RequestsExecutor.startGettingOfUpdates(
callbackQueryCallback = callbackQueryCallback, callbackQueryCallback = callbackQueryCallback,
shippingQueryCallback = shippingQueryCallback, shippingQueryCallback = shippingQueryCallback,
preCheckoutQueryCallback = preCheckoutQueryCallback, preCheckoutQueryCallback = preCheckoutQueryCallback,
pollCallback = pollCallback,
requestsDelayMillis = requestsDelayMillis, requestsDelayMillis = requestsDelayMillis,
scope = scope scope = scope
) )

View File

@ -1,23 +1,12 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions package com.github.insanusmokrassar.TelegramBotAPI.utils.extensions
import kotlinx.serialization.Serializable import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook.WebhookPrivateKeyConfig
import kotlinx.serialization.Transient
import java.io.FileInputStream
import java.security.KeyStore
@Serializable @Deprecated(
data class WebhookPrivateKeyConfig( "Replaced in separated package",
private val keyStorePath: String, ReplaceWith(
private val keyStorePassword: String, "WebhookPrivateKeyConfig",
val aliasName: String, "com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook.WebhookPrivateKeyConfig"
private val aliasPassword: String )
) { )
@Transient typealias WebhookPrivateKeyConfig = WebhookPrivateKeyConfig
val keyStore = KeyStore.getInstance("JKS").apply {
load(FileInputStream(keyStorePath), keyStorePassword())
}
fun keyStorePassword(): CharArray = keyStorePassword.toCharArray()
fun aliasPassword(): CharArray = aliasPassword.toCharArray()
}

View File

@ -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.RawUpdate
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate
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.webhook.WebhookPrivateKeyConfig
import com.github.insanusmokrassar.TelegramBotAPI.utils.toMediaGroupUpdate import com.github.insanusmokrassar.TelegramBotAPI.utils.toMediaGroupUpdate
import io.ktor.application.Application
import io.ktor.application.call import io.ktor.application.call
import io.ktor.request.receiveText import io.ktor.request.receiveText
import io.ktor.response.respond import io.ktor.response.respond