From 88a89ff1e7730b707e22f0a49ed8a40321696b5e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 14 Jan 2023 22:37:56 +0600 Subject: [PATCH] add resender module --- gradle.properties | 2 +- resender/build.gradle | 17 +++ .../src/commonMain/kotlin/MessageMetaInfo.kt | 18 +++ .../src/commonMain/kotlin/MessagesResender.kt | 144 ++++++++++++++++++ settings.gradle | 2 + 5 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 resender/build.gradle create mode 100644 resender/src/commonMain/kotlin/MessageMetaInfo.kt create mode 100644 resender/src/commonMain/kotlin/MessagesResender.kt diff --git a/gradle.properties b/gradle.properties index 9883b90..ae49d66 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ kotlin_serialisation_core_version=1.4.1 github_release_plugin_version=2.4.1 -tgbotapi_version=5.0.0 +tgbotapi_version=5.0.1-branch_5.0.1-build1361 micro_utils_version=0.16.4 exposed_version=0.41.1 plagubot_version=3.3.0 diff --git a/resender/build.gradle b/resender/build.gradle new file mode 100644 index 0000000..9a85f4f --- /dev/null +++ b/resender/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" +} + +apply from: "$mppJavaWithJsProjectPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api "dev.inmo:tgbotapi.core:$tgbotapi_version" + } + } + } +} + diff --git a/resender/src/commonMain/kotlin/MessageMetaInfo.kt b/resender/src/commonMain/kotlin/MessageMetaInfo.kt new file mode 100644 index 0000000..f844c63 --- /dev/null +++ b/resender/src/commonMain/kotlin/MessageMetaInfo.kt @@ -0,0 +1,18 @@ +package dev.inmo.tgbotapi.libraries.resender + +import dev.inmo.tgbotapi.types.IdChatIdentifier +import dev.inmo.tgbotapi.types.MessageId +import dev.inmo.tgbotapi.types.message.abstracts.Message +import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage +import kotlinx.serialization.Serializable + +@Serializable +data class MessageMetaInfo( + val chatId: IdChatIdentifier, + val messageId: MessageId, + val group: String? = null +) + +operator fun MessageMetaInfo.Companion.invoke( + message: Message +) = MessageMetaInfo(message.chat.id, message.messageId, (message as? PossiblyMediaGroupMessage<*>) ?.mediaGroupId) diff --git a/resender/src/commonMain/kotlin/MessagesResender.kt b/resender/src/commonMain/kotlin/MessagesResender.kt new file mode 100644 index 0000000..27c6444 --- /dev/null +++ b/resender/src/commonMain/kotlin/MessagesResender.kt @@ -0,0 +1,144 @@ +package dev.inmo.tgbotapi.libraries.resender + +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.media.SendMediaGroup +import dev.inmo.tgbotapi.types.ChatIdentifier +import dev.inmo.tgbotapi.types.IdChatIdentifier +import dev.inmo.tgbotapi.types.mediaCountInMediaGroup +import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage +import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent + +class MessagesResender( + private val bot: TelegramBot, + private val cacheChatId: ChatIdentifier +) { + suspend fun resend( + targetChatId: IdChatIdentifier, + messagesInfo: List + ): List> { + val orders = messagesInfo.mapIndexed { i, messageInfo -> messageInfo to i }.toMap() + val sortedMessagesContents = messagesInfo.groupBy { it.group }.flatMap { (group, list) -> + if (group == null) { + list.map { + orders.getValue(it) to listOf(it) + } + } else { + listOf(orders.getValue(list.first()) to list) + } + }.sortedBy { it.first } + + return sortedMessagesContents.flatMap { (_, contents) -> + val result = mutableListOf>() + + when { + contents.size == 1 -> { + val messageInfo = contents.first() + runCatching { + MessageMetaInfo( + targetChatId, + bot.execute( + CopyMessage( + targetChatId, + fromChatId = messageInfo.chatId, + messageId = messageInfo.messageId + ) + ) + ) + }.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 { + 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 { _ -> + result.add( + src to MessageMetaInfo( + targetChatId, + bot.execute( + CopyMessage( + targetChatId, + fromChatId = forwardedMessage.chat.id, + messageId = forwardedMessage.messageId + ) + ) + ) + ) + } ?: return@mapNotNull null) + } + + resultContents.singleOrNull() ?.also { (src, it) -> + result.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 { + result.add( + it.first to MessageMetaInfo( + partWrapper.sourceMessage.chat.id, + partWrapper.sourceMessage.messageId, + partWrapper.sourceMessage.mediaGroupId + ) + ) + } + } + } + } + } + + result.toList() + } + + } +} diff --git a/settings.gradle b/settings.gradle index ccfc849..feb9455 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,6 +7,8 @@ String[] includes = [ ":cache:content:common", ":cache:content:micro_utils", + + ":resender", ]