diff --git a/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheSettingsAPI.kt b/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheSettingsAPI.kt index b054e7f..867b385 100644 --- a/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheSettingsAPI.kt +++ b/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/AdminsCacheSettingsAPI.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.libraries.cache.admins import korlibs.time.minutes import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.Seconds +import korlibs.time.seconds import kotlinx.coroutines.flow.SharedFlow import kotlinx.serialization.Serializable diff --git a/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/DefaultAdminsCacheAPI.kt b/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/DefaultAdminsCacheAPI.kt index 04b162c..140fe6d 100644 --- a/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/DefaultAdminsCacheAPI.kt +++ b/cache/admins/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/admins/DefaultAdminsCacheAPI.kt @@ -8,6 +8,7 @@ import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.chat.ExtendedBot import dev.inmo.tgbotapi.types.chat.member.AdministratorChatMember import dev.inmo.tgbotapi.types.message.abstracts.* +import korlibs.time.seconds import kotlinx.serialization.Serializable interface DefaultAdminsCacheAPIRepo { diff --git a/resender/src/commonMain/kotlin/MessageMetaInfo.kt b/resender/src/commonMain/kotlin/MessageMetaInfo.kt index fa2ba2b..8b794e0 100644 --- a/resender/src/commonMain/kotlin/MessageMetaInfo.kt +++ b/resender/src/commonMain/kotlin/MessageMetaInfo.kt @@ -3,8 +3,10 @@ package dev.inmo.tgbotapi.libraries.resender import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.MessageId +import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage +import dev.inmo.tgbotapi.types.message.content.MediaGroupContent import kotlinx.serialization.Serializable @Serializable @@ -13,7 +15,20 @@ data class MessageMetaInfo( val chatId: IdChatIdentifier, val messageId: MessageId, val group: String? = null -) +) { + val metaInfo: Message.MetaInfo + get() = Message.MetaInfo(chatId, messageId) +} + +fun Message.asMessageMetaInfos(): List { + return if (this is ContentMessage<*>) { + (content as? MediaGroupContent<*>) ?.group ?.map { + MessageMetaInfo(it.sourceMessage.chat.id, it.sourceMessage.messageId, it.sourceMessage.mediaGroupId) + } + } else { + null + } ?: listOf(MessageMetaInfo(chat.id, messageId, (this as? PossiblyMediaGroupMessage<*>) ?.mediaGroupId)) +} operator fun MessageMetaInfo.Companion.invoke( message: Message diff --git a/resender/src/commonMain/kotlin/MessagesResender.kt b/resender/src/commonMain/kotlin/MessagesResender.kt index 9b71d81..d31d921 100644 --- a/resender/src/commonMain/kotlin/MessagesResender.kt +++ b/resender/src/commonMain/kotlin/MessagesResender.kt @@ -1,8 +1,10 @@ package dev.inmo.tgbotapi.libraries.resender +import dev.inmo.micro_utils.common.applyDiff import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.requests.ForwardMessage import dev.inmo.tgbotapi.requests.send.CopyMessage +import dev.inmo.tgbotapi.requests.send.CopyMessages import dev.inmo.tgbotapi.requests.send.media.SendMediaGroup import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.IdChatIdentifier @@ -19,135 +21,58 @@ class MessagesResender( messagesInfo: List, onBetweenMessages: suspend (sent: List, toBeSent: List) -> Unit ): List> { - val messagesWithOrders = messagesInfo.mapIndexed { i, messageInfo -> messageInfo to i }.toMap() - val ordersWithMessagesGroups = messagesInfo.groupBy { it.group }.flatMap { (group, list) -> - if (group == null) { - list.map { - messagesWithOrders.getValue(it) to listOf(it) - } - } else { - listOf(messagesWithOrders.getValue(list.first()) to list) - } - }.sortedBy { it.first } - - val sent = mutableListOf() - val leftToSend = ordersWithMessagesGroups.map { it.second }.toMutableList() - - return ordersWithMessagesGroups.flatMap { (_, contents) -> - val sourceMessagesToSentMessages = mutableListOf>() - - onBetweenMessages(sent.toList(), leftToSend.flatten()) - - when { - contents.size == 1 -> { - val messageInfo = contents.first() - runCatching { - MessageMetaInfo( - targetChatId, - bot.execute( - CopyMessage( - targetChatId, - fromChatId = messageInfo.chatId, - messageId = messageInfo.messageId - ) - ) + val currentGroup = mutableListOf() + suspend fun makeCopy(): List> { + currentGroup.sortBy { it.messageId } + while (currentGroup.isNotEmpty()) { + return runCatching { + bot.execute( + CopyMessages( + toChatId = targetChatId, + fromChatId = currentGroup.firstOrNull() ?.chatId ?: return emptyList(), + messageIds = currentGroup.map { it.messageId } ) - }.onFailure { _ -> - runCatching { - bot.execute( - ForwardMessage( - toChatId = targetChatId, - fromChatId = messageInfo.chatId, - messageId = messageInfo.messageId - ) - ) - }.onSuccess { - MessageMetaInfo( - targetChatId, + ).mapIndexed { i, newMessageId -> + currentGroup[i] to MessageMetaInfo(targetChatId, newMessageId) + }.also { + currentGroup.clear() + } + }.getOrElse { + currentGroup.applyDiff( + currentGroup.filter { + runCatching { bot.execute( - CopyMessage( - targetChatId, - fromChatId = it.chat.id, + ForwardMessage( + toChatId = cacheChatId, + fromChatId = it.chatId, messageId = it.messageId ) ) - ) + }.isSuccess } - }.getOrNull() ?.let { - sourceMessagesToSentMessages.add(messageInfo to it) - } - } - else -> { - val resultContents = contents.mapNotNull { - it to ( - bot.execute( - ForwardMessage( - toChatId = cacheChatId, - fromChatId = it.chatId, - messageId = it.messageId - ) - ) as? ContentMessage<*> ?: return@mapNotNull null) - }.mapNotNull { (src, forwardedMessage) -> - val forwardedMessageAsMediaPartMessage = forwardedMessage.takeIf { - it.content is MediaGroupPartContent - } ?.let { - it as ContentMessage - } - src to (forwardedMessageAsMediaPartMessage ?: null.also { _ -> - sourceMessagesToSentMessages.add( - src to MessageMetaInfo( - targetChatId, - bot.execute( - CopyMessage( - targetChatId, - fromChatId = forwardedMessage.chat.id, - messageId = forwardedMessage.messageId - ) - ) - ) - ) - } ?: return@mapNotNull null) - } - - resultContents.singleOrNull() ?.also { (src, it) -> - sourceMessagesToSentMessages.add( - src to MessageMetaInfo( - targetChatId, - bot.execute( - CopyMessage( - targetChatId, - it.chat.id, - it.messageId - ) - ) - ) - ) - } ?: resultContents.chunked(mediaCountInMediaGroup.last).forEach { - bot.execute( - SendMediaGroup( - targetChatId, - it.map { it.second.content.toMediaGroupMemberTelegramMedia() } - ) - ).content.group.mapIndexed { i, partWrapper -> - it.getOrNull(i) ?.let { - sourceMessagesToSentMessages.add( - it.first to MessageMetaInfo( - partWrapper.sourceMessage.chat.id, - partWrapper.sourceMessage.messageId, - partWrapper.sourceMessage.mediaGroupId - ) - ) - } - } - } - } + ) + null + } ?: continue } - - leftToSend.takeIf { it.isNotEmpty() } ?.removeAt(0) ?.also { - sent.addAll(it) - } - sourceMessagesToSentMessages.toList() + return emptyList() } + + val copied = mutableListOf>() + for (content in messagesInfo) { + when { + currentGroup.isEmpty() || + currentGroup.first().chatId == content.chatId -> currentGroup.add(content) + else -> { + onBetweenMessages(copied.map { it.first }, currentGroup.toList()) + copied.addAll(makeCopy()) + } + } + } + if (currentGroup.isNotEmpty()) { + onBetweenMessages(copied.map { it.first }, currentGroup.toList()) + copied.addAll(makeCopy()) + } + return copied.toList() } suspend fun resend(