diff --git a/resender/src/commonMain/kotlin/MessagesResender.kt b/resender/src/commonMain/kotlin/MessagesResender.kt index d31d921..b837b7f 100644 --- a/resender/src/commonMain/kotlin/MessagesResender.kt +++ b/resender/src/commonMain/kotlin/MessagesResender.kt @@ -3,6 +3,7 @@ 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.ForwardMessages import dev.inmo.tgbotapi.requests.send.CopyMessage import dev.inmo.tgbotapi.requests.send.CopyMessages import dev.inmo.tgbotapi.requests.send.media.SendMediaGroup @@ -21,58 +22,135 @@ class MessagesResender( messagesInfo: List, onBetweenMessages: suspend (sent: List, toBeSent: List) -> Unit ): List> { - 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 } + 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 + ) + ) ) - ).mapIndexed { i, newMessageId -> - currentGroup[i] to MessageMetaInfo(targetChatId, newMessageId) - }.also { - currentGroup.clear() + }.onFailure { _ -> + runCatching { + bot.execute( + ForwardMessage( + toChatId = targetChatId, + fromChatId = messageInfo.chatId, + messageId = messageInfo.messageId + ) + ) + }.onSuccess { + MessageMetaInfo( + targetChatId, + bot.execute( + CopyMessage( + targetChatId, + fromChatId = it.chat.id, + messageId = it.messageId + ) + ) + ) + } + }.getOrNull() ?.let { + sourceMessagesToSentMessages.add(messageInfo to it) } - }.getOrElse { - currentGroup.applyDiff( - currentGroup.filter { - runCatching { + } + else -> { + val resultContents = contents.mapNotNull { + it to ( bot.execute( ForwardMessage( toChatId = cacheChatId, fromChatId = it.chatId, messageId = it.messageId ) - ) - }.isSuccess + ) as? ContentMessage<*> ?: return@mapNotNull null) + }.mapNotNull { (src, forwardedMessage) -> + val forwardedMessageAsMediaPartMessage = forwardedMessage.takeIf { + it.content is MediaGroupPartContent + } ?.let { + it as ContentMessage } - ) - null - } ?: continue - } - return emptyList() - } + 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) + } - 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()) + 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 + ) + ) + } + } + } } } + + leftToSend.takeIf { it.isNotEmpty() } ?.removeAt(0) ?.also { + sent.addAll(it) + } + sourceMessagesToSentMessages.toList() } - if (currentGroup.isNotEmpty()) { - onBetweenMessages(copied.map { it.first }, currentGroup.toList()) - copied.addAll(makeCopy()) - } - return copied.toList() } suspend fun resend(