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/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/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/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..95b6330 --- /dev/null +++ b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt @@ -0,0 +1,101 @@ +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.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), + 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.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) + }.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( + newSticker + ), + (sticker as? CustomEmojiSticker) ?.needsRepainting ?: false + ).also { _ -> + reply( + it, + getStickerSet(stickerSetName).stickers.first() + ) + } + } + } + }.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 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 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"