From f152ede9b52a1cca7cc768adb13d914cf182de2c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 11 Mar 2023 01:00:31 +0600 Subject: [PATCH 1/4] improve sticker info bot --- .../src/commonMain/kotlin/StickerInfoBot.kt | 18 ++++++++++++++++++ gradle.properties | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt b/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt index 803b4ad..afcab3c 100644 --- a/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt +++ b/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt @@ -6,9 +6,21 @@ import dev.inmo.tgbotapi.extensions.api.get.* import dev.inmo.tgbotapi.extensions.api.send.* import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* +import dev.inmo.tgbotapi.types.StickerFormat import dev.inmo.tgbotapi.types.StickerType import dev.inmo.tgbotapi.types.message.textsources.* +import dev.inmo.tgbotapi.types.stickers.AnimatedStickerSet +import dev.inmo.tgbotapi.types.stickers.CustomEmojiSimpleStickerSet +import dev.inmo.tgbotapi.types.stickers.CustomEmojiStickerSet +import dev.inmo.tgbotapi.types.stickers.CustomEmojiVideoStickerSet +import dev.inmo.tgbotapi.types.stickers.MaskSimpleStickerSet +import dev.inmo.tgbotapi.types.stickers.MaskStickerSet +import dev.inmo.tgbotapi.types.stickers.MaskVideoStickerSet +import dev.inmo.tgbotapi.types.stickers.RegularSimpleStickerSet +import dev.inmo.tgbotapi.types.stickers.RegularStickerSet +import dev.inmo.tgbotapi.types.stickers.RegularVideoStickerSet import dev.inmo.tgbotapi.types.stickers.StickerSet +import dev.inmo.tgbotapi.types.stickers.UnknownStickerSet import dev.inmo.tgbotapi.utils.bold import dev.inmo.tgbotapi.utils.buildEntities import kotlinx.coroutines.* @@ -19,6 +31,12 @@ fun StickerSet?.buildInfo() = buildEntities { } else { bold("StickerSet name: ") + "${name}\n" bold("StickerSet title: ") + "${title}\n" + bold("Sticker format: ") + when (stickerFormat) { + StickerFormat.Animated -> "Animated" + StickerFormat.Static -> "Static" + is StickerFormat.Unknown -> stickerFormat.type + StickerFormat.Video -> "Video" + } + "\n" bold( when (stickerType) { StickerType.CustomEmoji -> "Custom emoji" diff --git a/gradle.properties b/gradle.properties index 2af7b52..64745c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx1g kotlin_version=1.8.10 -telegram_bot_api_version=6.0.3 -micro_utils_version=0.17.3 +telegram_bot_api_version=7.0.0 +micro_utils_version=0.17.5 serialization_version=1.5.0 ktor_version=2.2.4 From 7e7bbfaa93bb1da1ddb29a352afa0ddfcfdfe75d Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 11 Mar 2023 15:24:18 +0600 Subject: [PATCH 2/4] update version of telegram bot api and start including of stickers sets handling bot --- StickerSetHandler/build.gradle | 21 +++++++++++++++++++ .../src/main/kotlin/StickerSetHandlerBot.kt | 3 +++ gradle.properties | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 StickerSetHandler/build.gradle create mode 100644 StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt diff --git a/StickerSetHandler/build.gradle b/StickerSetHandler/build.gradle new file mode 100644 index 0000000..d58c310 --- /dev/null +++ b/StickerSetHandler/build.gradle @@ -0,0 +1,21 @@ +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin' +apply plugin: 'application' + +mainClassName="StickerSetHandlerBotKt" + + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + + implementation "dev.inmo:tgbotapi:$telegram_bot_api_version" +} diff --git a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt new file mode 100644 index 0000000..7507cd5 --- /dev/null +++ b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt @@ -0,0 +1,3 @@ +suspend fun main(args: Array) { + build +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 64745c5..d217a5a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx1g kotlin_version=1.8.10 -telegram_bot_api_version=7.0.0 +telegram_bot_api_version=7.0.0-branch_7.0.0-build1551 micro_utils_version=0.17.5 serialization_version=1.5.0 ktor_version=2.2.4 From 8ef50537aeabcd5617af4088e79b23f92198dd1c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 11 Mar 2023 15:55:09 +0600 Subject: [PATCH 3/4] some functionality of sticker set handler bot --- .../src/main/kotlin/StickerSetHandlerBot.kt | 47 ++++++++++++++++++- settings.gradle | 2 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt index 7507cd5..1ed11d4 100644 --- a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt +++ b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt @@ -1,3 +1,48 @@ +import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.tgbotapi.extensions.api.bot.getMe +import dev.inmo.tgbotapi.extensions.api.files.downloadFile +import dev.inmo.tgbotapi.extensions.api.files.downloadFileToTemp +import dev.inmo.tgbotapi.extensions.api.get.getStickerSet +import dev.inmo.tgbotapi.extensions.api.stickers.createNewStickerSet +import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onSticker +import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sticker +import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile +import dev.inmo.tgbotapi.requests.stickers.InputSticker +import dev.inmo.tgbotapi.types.files.* +import dev.inmo.tgbotapi.types.toChatId +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers + suspend fun main(args: Array) { - build + telegramBotWithBehaviourAndLongPolling(args.first(), scope = CoroutineScope(Dispatchers.IO)) { + val me = getMe() + onSticker { + val stickerSetName = "${it.chat.id}_by_${me.username.username}" + val sticker = it.content.media + runCatchingSafely { + getStickerSet(stickerSetName) + }.getOrElse { _ -> + createNewStickerSet( + it.chat.id.toChatId(), + stickerSetName, + "Sticker set by ${me.firstName}", + it.content.media.stickerFormat, + listOf( + when (sticker) { + is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji( + downloadFileToTemp(sticker.fileId).asMultipartFile(), + sticker.emoji ?.let(::listOf) ?: emptyList(), + emptyList() + ) + is MaskSticker -> TODO() + is RegularSticker -> TODO() + is UnknownSticker -> TODO() + } + ), + sticker + ) + } + } + } } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index d7e3bf9..dde1eba 100644 --- a/settings.gradle +++ b/settings.gradle @@ -34,3 +34,5 @@ include ":UserChatShared" include ":RightsChangerBot" include ":LiveLocationsBot" + +include ":StickerSetHandler" From 253328f49abdf2859176a68b2223ba3d1cfedb0a Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 11 Mar 2023 21:39:08 +0600 Subject: [PATCH 4/4] complete sample with sticker set handler example --- .../src/main/kotlin/FilesLoaderBot.kt | 94 ++++++++++++++++++- StickerSetHandler/README.md | 9 ++ .../src/main/kotlin/StickerSetHandlerBot.kt | 87 +++++++++++++---- WebApp/README.md | 2 +- gradle.properties | 2 +- 5 files changed, 171 insertions(+), 23 deletions(-) create mode 100644 StickerSetHandler/README.md diff --git a/FilesLoaderBot/src/main/kotlin/FilesLoaderBot.kt b/FilesLoaderBot/src/main/kotlin/FilesLoaderBot.kt index 58dbd1a..f477391 100644 --- a/FilesLoaderBot/src/main/kotlin/FilesLoaderBot.kt +++ b/FilesLoaderBot/src/main/kotlin/FilesLoaderBot.kt @@ -1,10 +1,39 @@ +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.tgbotapi.extensions.api.files.downloadFile +import dev.inmo.tgbotapi.extensions.api.files.downloadFileToTemp import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo import dev.inmo.tgbotapi.extensions.api.send.reply +import dev.inmo.tgbotapi.extensions.api.send.replyWithAnimation +import dev.inmo.tgbotapi.extensions.api.send.replyWithAudio +import dev.inmo.tgbotapi.extensions.api.send.replyWithDocument +import dev.inmo.tgbotapi.extensions.api.send.replyWithMediaGroup +import dev.inmo.tgbotapi.extensions.api.send.replyWithPhoto +import dev.inmo.tgbotapi.extensions.api.send.replyWithSticker +import dev.inmo.tgbotapi.extensions.api.send.replyWithVideo +import dev.inmo.tgbotapi.extensions.api.send.replyWithVideoNote +import dev.inmo.tgbotapi.extensions.api.send.replyWithVoice +import dev.inmo.tgbotapi.extensions.api.send.withAction import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMedia +import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile +import dev.inmo.tgbotapi.requests.send.SendAction +import dev.inmo.tgbotapi.types.actions.BotAction +import dev.inmo.tgbotapi.types.actions.TypingAction +import dev.inmo.tgbotapi.types.media.TelegramMediaAudio +import dev.inmo.tgbotapi.types.media.TelegramMediaDocument +import dev.inmo.tgbotapi.types.media.TelegramMediaPhoto +import dev.inmo.tgbotapi.types.media.TelegramMediaVideo +import dev.inmo.tgbotapi.types.message.content.AnimationContent +import dev.inmo.tgbotapi.types.message.content.AudioContent +import dev.inmo.tgbotapi.types.message.content.DocumentContent +import dev.inmo.tgbotapi.types.message.content.MediaGroupContent +import dev.inmo.tgbotapi.types.message.content.PhotoContent +import dev.inmo.tgbotapi.types.message.content.StickerContent +import dev.inmo.tgbotapi.types.message.content.VideoContent +import dev.inmo.tgbotapi.types.message.content.VideoNoteContent +import dev.inmo.tgbotapi.types.message.content.VoiceContent import dev.inmo.tgbotapi.utils.filenameFromUrl import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -23,15 +52,72 @@ suspend fun main(args: Array) { reply(it, "Send me any media (like photo or video) to download it") } onMedia(initialFilter = null) { - val pathedFile = bot.getFileAdditionalInfo(it.content.media) + val content = it.content + val pathedFile = bot.getFileAdditionalInfo(content.media) val outFile = File(directoryOrFile, pathedFile.filePath.filenameFromUrl) runCatching { - bot.downloadFile(it.content.media, outFile) + bot.downloadFile(content.media, outFile) }.onFailure { it.printStackTrace() + }.onSuccess { _ -> + reply(it, "Saved to ${outFile.absolutePath}") + withAction(it.chat.id, TypingAction) { + when (content) { + is PhotoContent -> replyWithPhoto( + it, + outFile.asMultipartFile() + ) + is AnimationContent -> replyWithAnimation( + it, + outFile.asMultipartFile() + ) + is VideoContent -> replyWithVideo( + it, + outFile.asMultipartFile() + ) + is StickerContent -> replyWithSticker( + it, + outFile.asMultipartFile() + ) + is MediaGroupContent<*> -> replyWithMediaGroup( + it, + content.group.map { + when (val innerContent = it.content) { + is AudioContent -> TelegramMediaAudio( + downloadFileToTemp(innerContent.media).asMultipartFile() + ) + is DocumentContent -> TelegramMediaDocument( + downloadFileToTemp(innerContent.media).asMultipartFile() + ) + is PhotoContent -> TelegramMediaPhoto( + downloadFileToTemp(innerContent.media).asMultipartFile() + ) + is VideoContent -> TelegramMediaVideo( + downloadFileToTemp(innerContent.media).asMultipartFile() + ) + } + } + ) + is AudioContent -> replyWithAudio( + it, + outFile.asMultipartFile() + ) + is DocumentContent -> replyWithDocument( + it, + outFile.asMultipartFile() + ) + is VoiceContent -> replyWithVoice( + it, + outFile.asMultipartFile() + ) + is VideoNoteContent -> replyWithVideoNote( + it, + outFile.asMultipartFile() + ) + } + } } - reply(it, "Saved to ${outFile.absolutePath}") } - onContentMessage { println(it) } + allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) } }.second.join() } diff --git a/StickerSetHandler/README.md b/StickerSetHandler/README.md new file mode 100644 index 0000000..6849019 --- /dev/null +++ b/StickerSetHandler/README.md @@ -0,0 +1,9 @@ +# StickerSetHandler + +Send sticker to this bot to form your own stickers set. Send /delete to delete this sticker set + +## How to run + +```bash +./gradlew run --args="TOKEN" +``` diff --git a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt index 1ed11d4..95b6330 100644 --- a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt +++ b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt @@ -3,46 +3,99 @@ import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.files.downloadFile import dev.inmo.tgbotapi.extensions.api.files.downloadFileToTemp import dev.inmo.tgbotapi.extensions.api.get.getStickerSet +import dev.inmo.tgbotapi.extensions.api.send.reply +import dev.inmo.tgbotapi.extensions.api.stickers.addStickerToSet import dev.inmo.tgbotapi.extensions.api.stickers.createNewStickerSet +import dev.inmo.tgbotapi.extensions.api.stickers.deleteStickerSet import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onSticker import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sticker import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile import dev.inmo.tgbotapi.requests.stickers.InputSticker +import dev.inmo.tgbotapi.types.chat.Chat import dev.inmo.tgbotapi.types.files.* import dev.inmo.tgbotapi.types.toChatId +import dev.inmo.tgbotapi.utils.botCommand import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +/** + * Send sticker to this bot to form your own stickers set. Send /delete to delete this sticker set + */ suspend fun main(args: Array) { - telegramBotWithBehaviourAndLongPolling(args.first(), scope = CoroutineScope(Dispatchers.IO)) { + telegramBotWithBehaviourAndLongPolling( + args.first(), + scope = CoroutineScope(Dispatchers.IO), + defaultExceptionsHandler = { + it.printStackTrace() + } + ) { val me = getMe() + fun Chat.stickerSetName() = "s${id.chatId}_by_${me.username.usernameWithoutAt}" + onCommand("start") { + reply(it) { + botCommand("delete") + " - to clear stickers" + } + } + onCommand("delete") { + val deleted = runCatchingSafely { + deleteStickerSet(it.chat.stickerSetName()) + }.getOrElse { false } + + if (deleted) { + reply(it, "Deleted") + } else { + reply(it, "Can't delete for some of reason") + } + } onSticker { - val stickerSetName = "${it.chat.id}_by_${me.username.username}" + val stickerSetName = it.chat.stickerSetName() val sticker = it.content.media + val newSticker = when (sticker) { + is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji( + downloadFileToTemp(sticker.fileId).asMultipartFile(), + listOf(sticker.emoji ?: "\uD83D\uDE0A"), + emptyList() + ) + is MaskSticker -> InputSticker.Mask( + downloadFileToTemp(sticker.fileId).asMultipartFile(), + listOf(sticker.emoji ?: "\uD83D\uDE0A"), + sticker.maskPosition + ) + is RegularSticker -> InputSticker.WithKeywords.Regular( + downloadFileToTemp(sticker.fileId).asMultipartFile(), + listOf(sticker.emoji ?: "\uD83D\uDE0A"), + emptyList() + ) + is UnknownSticker -> return@onSticker + } runCatchingSafely { getStickerSet(stickerSetName) - }.getOrElse { _ -> + }.onSuccess { stickerSet -> + addStickerToSet(it.chat.id.toChatId(), stickerSet.name, newSticker).also { _ -> + reply( + it, + getStickerSet(stickerSetName).stickers.last() + ) + } + }.onFailure { _ -> createNewStickerSet( it.chat.id.toChatId(), stickerSetName, "Sticker set by ${me.firstName}", it.content.media.stickerFormat, listOf( - when (sticker) { - is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji( - downloadFileToTemp(sticker.fileId).asMultipartFile(), - sticker.emoji ?.let(::listOf) ?: emptyList(), - emptyList() - ) - is MaskSticker -> TODO() - is RegularSticker -> TODO() - is UnknownSticker -> TODO() - } + newSticker ), - sticker - ) + (sticker as? CustomEmojiSticker) ?.needsRepainting ?: false + ).also { _ -> + reply( + it, + getStickerSet(stickerSetName).stickers.first() + ) + } } } - } -} \ No newline at end of file + }.second.join() +} diff --git a/WebApp/README.md b/WebApp/README.md index 4275aab..aede3d6 100644 --- a/WebApp/README.md +++ b/WebApp/README.md @@ -12,6 +12,6 @@ What is there in this module: ## How to run -```kotlin +```bash ./gradlew run --args="TOKEN WEB_APP_ADDRESS" ``` diff --git a/gradle.properties b/gradle.properties index d217a5a..64745c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx1g kotlin_version=1.8.10 -telegram_bot_api_version=7.0.0-branch_7.0.0-build1551 +telegram_bot_api_version=7.0.0 micro_utils_version=0.17.5 serialization_version=1.5.0 ktor_version=2.2.4