improvements in MessagesResender

This commit is contained in:
InsanusMokrassar 2024-01-13 14:37:21 +06:00
parent f19664da58
commit 4057d5167f
4 changed files with 64 additions and 122 deletions

View File

@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.libraries.cache.admins
import korlibs.time.minutes import korlibs.time.minutes
import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.IdChatIdentifier
import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.Seconds
import korlibs.time.seconds
import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharedFlow
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -8,6 +8,7 @@ import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.ExtendedBot import dev.inmo.tgbotapi.types.chat.ExtendedBot
import dev.inmo.tgbotapi.types.chat.member.AdministratorChatMember import dev.inmo.tgbotapi.types.chat.member.AdministratorChatMember
import dev.inmo.tgbotapi.types.message.abstracts.* import dev.inmo.tgbotapi.types.message.abstracts.*
import korlibs.time.seconds
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
interface DefaultAdminsCacheAPIRepo { interface DefaultAdminsCacheAPIRepo {

View File

@ -3,8 +3,10 @@ package dev.inmo.tgbotapi.libraries.resender
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.IdChatIdentifier
import dev.inmo.tgbotapi.types.MessageId 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.Message
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@ -13,7 +15,20 @@ data class MessageMetaInfo(
val chatId: IdChatIdentifier, val chatId: IdChatIdentifier,
val messageId: MessageId, val messageId: MessageId,
val group: String? = null val group: String? = null
) ) {
val metaInfo: Message.MetaInfo
get() = Message.MetaInfo(chatId, messageId)
}
fun Message.asMessageMetaInfos(): List<MessageMetaInfo> {
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( operator fun MessageMetaInfo.Companion.invoke(
message: Message message: Message

View File

@ -1,8 +1,10 @@
package dev.inmo.tgbotapi.libraries.resender package dev.inmo.tgbotapi.libraries.resender
import dev.inmo.micro_utils.common.applyDiff
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.ForwardMessage import dev.inmo.tgbotapi.requests.ForwardMessage
import dev.inmo.tgbotapi.requests.send.CopyMessage 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.requests.send.media.SendMediaGroup
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.IdChatIdentifier
@ -19,135 +21,58 @@ class MessagesResender(
messagesInfo: List<MessageMetaInfo>, messagesInfo: List<MessageMetaInfo>,
onBetweenMessages: suspend (sent: List<MessageMetaInfo>, toBeSent: List<MessageMetaInfo>) -> Unit onBetweenMessages: suspend (sent: List<MessageMetaInfo>, toBeSent: List<MessageMetaInfo>) -> Unit
): List<Pair<MessageMetaInfo, MessageMetaInfo>> { ): List<Pair<MessageMetaInfo, MessageMetaInfo>> {
val messagesWithOrders = messagesInfo.mapIndexed { i, messageInfo -> messageInfo to i }.toMap() val currentGroup = mutableListOf<MessageMetaInfo>()
val ordersWithMessagesGroups = messagesInfo.groupBy { it.group }.flatMap { (group, list) -> suspend fun makeCopy(): List<Pair<MessageMetaInfo, MessageMetaInfo>> {
if (group == null) { currentGroup.sortBy { it.messageId }
list.map { while (currentGroup.isNotEmpty()) {
messagesWithOrders.getValue(it) to listOf(it) return runCatching {
}
} else {
listOf(messagesWithOrders.getValue(list.first()) to list)
}
}.sortedBy { it.first }
val sent = mutableListOf<MessageMetaInfo>()
val leftToSend = ordersWithMessagesGroups.map { it.second }.toMutableList()
return ordersWithMessagesGroups.flatMap { (_, contents) ->
val sourceMessagesToSentMessages = mutableListOf<Pair<MessageMetaInfo, MessageMetaInfo>>()
onBetweenMessages(sent.toList(), leftToSend.flatten())
when {
contents.size == 1 -> {
val messageInfo = contents.first()
runCatching {
MessageMetaInfo(
targetChatId,
bot.execute( bot.execute(
CopyMessage( CopyMessages(
targetChatId,
fromChatId = messageInfo.chatId,
messageId = messageInfo.messageId
)
)
)
}.onFailure { _ ->
runCatching {
bot.execute(
ForwardMessage(
toChatId = targetChatId, toChatId = targetChatId,
fromChatId = messageInfo.chatId, fromChatId = currentGroup.firstOrNull() ?.chatId ?: return emptyList(),
messageId = messageInfo.messageId messageIds = currentGroup.map { it.messageId }
)
)
}.onSuccess {
MessageMetaInfo(
targetChatId,
bot.execute(
CopyMessage(
targetChatId,
fromChatId = it.chat.id,
messageId = it.messageId
)
)
) )
).mapIndexed { i, newMessageId ->
currentGroup[i] to MessageMetaInfo(targetChatId, newMessageId)
}.also {
currentGroup.clear()
} }
}.getOrNull() ?.let { }.getOrElse {
sourceMessagesToSentMessages.add(messageInfo to it) currentGroup.applyDiff(
} currentGroup.filter {
} runCatching {
else -> {
val resultContents = contents.mapNotNull {
it to (
bot.execute( bot.execute(
ForwardMessage( ForwardMessage(
toChatId = cacheChatId, toChatId = cacheChatId,
fromChatId = it.chatId, fromChatId = it.chatId,
messageId = it.messageId messageId = it.messageId
) )
) as? ContentMessage<*> ?: return@mapNotNull null) )
}.mapNotNull { (src, forwardedMessage) -> }.isSuccess
val forwardedMessageAsMediaPartMessage = forwardedMessage.takeIf {
it.content is MediaGroupPartContent
} ?.let {
it as ContentMessage<MediaGroupPartContent>
} }
src to (forwardedMessageAsMediaPartMessage ?: null.also { _ ->
sourceMessagesToSentMessages.add(
src to MessageMetaInfo(
targetChatId,
bot.execute(
CopyMessage(
targetChatId,
fromChatId = forwardedMessage.chat.id,
messageId = forwardedMessage.messageId
) )
) null
) } ?: continue
) }
} ?: return@mapNotNull null) return emptyList()
} }
resultContents.singleOrNull() ?.also { (src, it) -> val copied = mutableListOf<Pair<MessageMetaInfo, MessageMetaInfo>>()
sourceMessagesToSentMessages.add( for (content in messagesInfo) {
src to MessageMetaInfo( when {
targetChatId, currentGroup.isEmpty() ||
bot.execute( currentGroup.first().chatId == content.chatId -> currentGroup.add(content)
CopyMessage( else -> {
targetChatId, onBetweenMessages(copied.map { it.first }, currentGroup.toList())
it.chat.id, copied.addAll(makeCopy())
it.messageId
)
)
)
)
} ?: resultContents.chunked(mediaCountInMediaGroup.last).forEach {
bot.execute(
SendMediaGroup<MediaGroupPartContent>(
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
)
)
} }
} }
} }
if (currentGroup.isNotEmpty()) {
onBetweenMessages(copied.map { it.first }, currentGroup.toList())
copied.addAll(makeCopy())
} }
} return copied.toList()
leftToSend.takeIf { it.isNotEmpty() } ?.removeAt(0) ?.also {
sent.addAll(it)
}
sourceMessagesToSentMessages.toList()
}
} }
suspend fun resend( suspend fun resend(