From b660bf5f4200c926b8b512d70e70068a2817c178 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 18 Apr 2024 17:03:53 +0600 Subject: [PATCH 1/4] upgrade to support new ktgbotapi --- HelloBot/src/main/kotlin/HelloBot.kt | 4 ++++ .../src/commonMain/kotlin/StickerInfoBot.kt | 13 ------------- .../src/main/kotlin/StickerSetHandlerBot.kt | 4 +++- gradle.properties | 2 +- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/HelloBot/src/main/kotlin/HelloBot.kt b/HelloBot/src/main/kotlin/HelloBot.kt index 71c5778..fb95839 100644 --- a/HelloBot/src/main/kotlin/HelloBot.kt +++ b/HelloBot/src/main/kotlin/HelloBot.kt @@ -56,6 +56,10 @@ suspend fun main(vararg args: String) { } ?: chat.title } } + is PreviewBusinessChat -> { + reply(message, "Hi, " + "${chat.original.firstName} ${chat.original.lastName} (as business chat :) )".textMentionMarkdownV2(chat.original.id), MarkdownV2) + return@onMentionWithAnyContent + } is UnknownChatType -> "Unknown :(".escapeMarkdownV2Common() } reply( diff --git a/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt b/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt index ddd9f00..9b1dc06 100644 --- a/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt +++ b/StickerInfoBot/StickerInfoBotLib/src/commonMain/kotlin/StickerInfoBot.kt @@ -9,16 +9,9 @@ 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 @@ -31,12 +24,6 @@ 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/src/main/kotlin/StickerSetHandlerBot.kt b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt index 8a9cf65..9cefc7a 100644 --- a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt +++ b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt @@ -56,16 +56,19 @@ suspend fun main(args: Array) { val newSticker = when (sticker) { is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji( downloadFileToTemp(sticker.fileId).asMultipartFile(), + sticker.stickerFormat, listOf(sticker.emoji ?: "\uD83D\uDE0A"), emptyList() ) is MaskSticker -> InputSticker.Mask( downloadFileToTemp(sticker.fileId).asMultipartFile(), + sticker.stickerFormat, listOf(sticker.emoji ?: "\uD83D\uDE0A"), sticker.maskPosition ) is RegularSticker -> InputSticker.WithKeywords.Regular( downloadFileToTemp(sticker.fileId).asMultipartFile(), + sticker.stickerFormat, listOf(sticker.emoji ?: "\uD83D\uDE0A"), emptyList() ) @@ -85,7 +88,6 @@ suspend fun main(args: Array) { it.chat.id.toChatId(), stickerSetName.string, "Sticker set by ${me.firstName}", - it.content.media.stickerFormat, listOf( newSticker ), diff --git a/gradle.properties b/gradle.properties index da91621..f1971db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx2344m kotlin_version=1.9.23 -telegram_bot_api_version=11.0.0 +telegram_bot_api_version=12.0.0 micro_utils_version=0.20.39 serialization_version=1.6.3 ktor_version=2.3.9 From c04a367375f87fc05450da15c8642b30333727d1 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 18 Apr 2024 20:06:59 +0600 Subject: [PATCH 2/4] fixes and improvements --- FSMBot/src/main/kotlin/SimpleFSMBot.kt | 18 +++++++++++++++++- .../src/commonMain/kotlin/ResenderBot.kt | 2 ++ .../src/main/kotlin/StickerSetHandlerBot.kt | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/FSMBot/src/main/kotlin/SimpleFSMBot.kt b/FSMBot/src/main/kotlin/SimpleFSMBot.kt index c5b6c21..030299a 100644 --- a/FSMBot/src/main/kotlin/SimpleFSMBot.kt +++ b/FSMBot/src/main/kotlin/SimpleFSMBot.kt @@ -1,4 +1,5 @@ import dev.inmo.micro_utils.coroutines.AccumulatorFlow +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.fsm.common.State import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.api.send.sendMessage @@ -8,6 +9,8 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs import dev.inmo.tgbotapi.extensions.utils.extensions.sameThread import dev.inmo.tgbotapi.extensions.utils.formatting.* +import dev.inmo.tgbotapi.extensions.utils.textContentOrNull +import dev.inmo.tgbotapi.extensions.utils.withContentOrNull import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.MessageThreadId import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage @@ -54,7 +57,8 @@ suspend fun main(args: Array) { val content = contentMessage.content when { - content is TextContent && content.parseCommandsWithArgs().keys.contains("stop") -> StopState(it.context) + content is TextContent && content.text == "/stop" + || content is TextContent && content.parseCommandsWithArgs().keys.contains("stop") -> StopState(it.context) else -> { execute(content.createResend(it.context)) it @@ -72,5 +76,17 @@ suspend fun main(args: Array) { ) { startChain(ExpectContentOrStopState(it.chat.id, it)) } + + onContentMessage( + { + it.content.textContentOrNull() ?.text == "/start" + } + ) { + startChain(ExpectContentOrStopState(it.chat.id, it.withContentOrNull() ?: return@onContentMessage)) + } + + allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { + println(it) + } }.second.join() } diff --git a/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt b/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt index 52e566c..4bbf65b 100644 --- a/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt +++ b/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt @@ -10,6 +10,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.utils.shortcuts.* import dev.inmo.tgbotapi.extensions.utils.withContentOrNull import dev.inmo.tgbotapi.types.ReplyParameters +import dev.inmo.tgbotapi.types.message.abstracts.BusinessContentMessage import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.quoteEntitiesField import dev.inmo.tgbotapi.utils.extensions.threadIdOrNull @@ -22,6 +23,7 @@ suspend fun activateResenderBot( telegramBotWithBehaviourAndLongPolling(token, scope = CoroutineScope(currentCoroutineContext() + SupervisorJob())) { onContentMessage( subcontextUpdatesFilter = MessageFilterByChat, + initialFilter = { it !is BusinessContentMessage<*> || !it.sentByBusinessConnectionOwner } ) { val chat = it.chat diff --git a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt index 9cefc7a..db0c802 100644 --- a/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt +++ b/StickerSetHandler/src/main/kotlin/StickerSetHandlerBot.kt @@ -83,7 +83,7 @@ suspend fun main(args: Array) { getStickerSet(stickerSetName).stickers.last() ) } - }.onFailure { _ -> + }.onFailure { exception -> createNewStickerSet( it.chat.id.toChatId(), stickerSetName.string, From d6a6ad8d37f15fbf9913097a8ee6a3dd0346d130 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 19 Apr 2024 18:10:46 +0600 Subject: [PATCH 3/4] improvements in samples --- BusinessConnectionsBot/README.md | 9 ++ BusinessConnectionsBot/build.gradle | 21 +++++ .../src/main/kotlin/BusinessConnectionsBot.kt | 85 +++++++++++++++++++ .../src/main/kotlin/UserChatShared.kt | 13 +++ settings.gradle | 2 + 5 files changed, 130 insertions(+) create mode 100644 BusinessConnectionsBot/README.md create mode 100644 BusinessConnectionsBot/build.gradle create mode 100644 BusinessConnectionsBot/src/main/kotlin/BusinessConnectionsBot.kt diff --git a/BusinessConnectionsBot/README.md b/BusinessConnectionsBot/README.md new file mode 100644 index 0000000..2461998 --- /dev/null +++ b/BusinessConnectionsBot/README.md @@ -0,0 +1,9 @@ +# BusinessConnectionBotBot + +When bot connected or disconnected to the business chat, it will notify this chat + +## Launch + +```bash +../gradlew run --args="BOT_TOKEN" +``` diff --git a/BusinessConnectionsBot/build.gradle b/BusinessConnectionsBot/build.gradle new file mode 100644 index 0000000..14a48e1 --- /dev/null +++ b/BusinessConnectionsBot/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="BusinessConnectionsBotKt" + + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + + implementation "dev.inmo:tgbotapi:$telegram_bot_api_version" +} diff --git a/BusinessConnectionsBot/src/main/kotlin/BusinessConnectionsBot.kt b/BusinessConnectionsBot/src/main/kotlin/BusinessConnectionsBot.kt new file mode 100644 index 0000000..49f79a1 --- /dev/null +++ b/BusinessConnectionsBot/src/main/kotlin/BusinessConnectionsBot.kt @@ -0,0 +1,85 @@ +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.LogLevel +import dev.inmo.kslog.common.defaultMessageFormatter +import dev.inmo.kslog.common.setDefaultKSLog +import dev.inmo.tgbotapi.extensions.api.bot.getMe +import dev.inmo.tgbotapi.extensions.api.get.getBusinessConnection +import dev.inmo.tgbotapi.extensions.api.send.reply +import dev.inmo.tgbotapi.extensions.api.send.send +import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* +import dev.inmo.tgbotapi.extensions.utils.ifBusinessContentMessage +import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +suspend fun main(args: Array) { + val botToken = args.first() + val isDebug = args.getOrNull(1) == "debug" + + if (isDebug) { + setDefaultKSLog( + KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? -> + println(defaultMessageFormatter(level, tag, message, throwable)) + } + ) + } + + val businessConnectionsChats = mutableMapOf() + val businessConnectionsChatsMutex = Mutex() + + telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) { + val me = getMe() + println(me) + + onBusinessConnectionEnabled { + businessConnectionsChatsMutex.withLock { + businessConnectionsChats[it.id] = it.userChatId + } + send(it.userChatId, "Business connection ${it.businessConnectionId.string} has been enabled") + } + onBusinessConnectionDisabled { + businessConnectionsChatsMutex.withLock { + businessConnectionsChats.remove(it.id) + } + send(it.userChatId, "Business connection ${it.businessConnectionId.string} has been disabled") + } + + onContentMessage { + it.ifBusinessContentMessage { + val sent = execute(it.content.createResend(it.from.id)) + if (it.sentByBusinessConnectionOwner) { + reply(sent, "You have sent this message to the ${it.businessConnectionId.string} related chat") + } else { + reply(sent, "User have sent this message to you in the ${it.businessConnectionId.string} related chat") + } + } + } + onEditedContentMessage { + it.ifBusinessContentMessage { + val sent = execute(it.content.createResend(it.from.id)) + if (it.sentByBusinessConnectionOwner) { + reply(sent, "You have edited this message in the ${it.businessConnectionId.string} related chat") + } else { + reply(sent, "User have edited this message to you in the ${it.businessConnectionId.string} related chat") + } + } + } + onBusinessMessagesDeleted { + var businessConnectionOwnerChat = businessConnectionsChatsMutex.withLock { + businessConnectionsChats[it.businessConnectionId] + } + if (businessConnectionOwnerChat == null) { + val businessConnection = getBusinessConnection(it.businessConnectionId) + businessConnectionsChatsMutex.withLock { + businessConnectionsChats[businessConnection.businessConnectionId] = businessConnection.userChatId + } + businessConnectionOwnerChat = businessConnection.userChatId + } + send(businessConnectionOwnerChat, "There are several removed messages in chat ${it.chat.id}: ${it.messageIds}") + } + }.second.join() +} \ No newline at end of file diff --git a/UserChatShared/src/main/kotlin/UserChatShared.kt b/UserChatShared/src/main/kotlin/UserChatShared.kt index c55102a..817e61a 100644 --- a/UserChatShared/src/main/kotlin/UserChatShared.kt +++ b/UserChatShared/src/main/kotlin/UserChatShared.kt @@ -1,3 +1,7 @@ +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.LogLevel +import dev.inmo.kslog.common.defaultMessageFormatter +import dev.inmo.kslog.common.setDefaultKSLog import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands @@ -18,6 +22,15 @@ import dev.inmo.tgbotapi.utils.row suspend fun main(args: Array) { val botToken = args.first() + val isDebug = args.getOrNull(1) == "debug" + + if (isDebug) { + setDefaultKSLog( + KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? -> + println(defaultMessageFormatter(level, tag, message, throwable)) + } + ) + } val bot = telegramBot(botToken) diff --git a/settings.gradle b/settings.gradle index a5231ca..57b91bf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -47,3 +47,5 @@ include ":ReactionsInfoBot" include ":LinkPreviewsBot" include ":BoostsInfoBot" + +include ":BusinessConnectionsBot" From 11a97c520a296f574c50aeb404ddeaaa5f547543 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 19 Apr 2024 19:34:48 +0600 Subject: [PATCH 4/4] update --- .../src/main/kotlin/UserChatShared.kt | 115 ++++++++++++++---- 1 file changed, 92 insertions(+), 23 deletions(-) diff --git a/UserChatShared/src/main/kotlin/UserChatShared.kt b/UserChatShared/src/main/kotlin/UserChatShared.kt index 817e61a..895d29a 100644 --- a/UserChatShared/src/main/kotlin/UserChatShared.kt +++ b/UserChatShared/src/main/kotlin/UserChatShared.kt @@ -68,35 +68,53 @@ suspend fun main(args: Array) { row { requestUserOrBotButton( "\uD83D\uDC64/\uD83E\uDD16 (1)", - requestIdUserOrBot + requestIdUserOrBot, + requestName = true, + requestUsername = true, + requestPhoto = true ) } row { requestUserButton( "\uD83D\uDC64☆ (1)", requestIdUserNonPremium, - premiumUser = false + premiumUser = false, + requestName = true, + requestUsername = true, + requestPhoto = true ) requestUserButton( "\uD83D\uDC64 (1)", requestIdUserAny, - premiumUser = null + premiumUser = null, + requestName = true, + requestUsername = true, + requestPhoto = true ) requestUserButton( "\uD83D\uDC64★ (1)", requestIdUserPremium, - premiumUser = true + premiumUser = true, + requestName = true, + requestUsername = true, + requestPhoto = true ) requestBotButton( "\uD83E\uDD16 (1)", - requestIdBot + requestIdBot, + requestName = true, + requestUsername = true, + requestPhoto = true ) } row { requestUsersOrBotsButton( "\uD83D\uDC64/\uD83E\uDD16", requestIdUsersOrBots, - maxCount = keyboardButtonRequestUserLimit.last + maxCount = keyboardButtonRequestUserLimit.last, + requestName = true, + requestUsername = true, + requestPhoto = true ) } row { @@ -104,101 +122,152 @@ suspend fun main(args: Array) { "\uD83D\uDC64☆", requestIdUsersNonPremium, premiumUser = false, - maxCount = keyboardButtonRequestUserLimit.last + maxCount = keyboardButtonRequestUserLimit.last, + requestName = true, + requestUsername = true, + requestPhoto = true ) requestUsersButton( "\uD83D\uDC64", requestIdUsersAny, premiumUser = null, - maxCount = keyboardButtonRequestUserLimit.last + maxCount = keyboardButtonRequestUserLimit.last, + requestName = true, + requestUsername = true, + requestPhoto = true ) requestUsersButton( "\uD83D\uDC64★", requestIdUsersPremium, premiumUser = true, - maxCount = keyboardButtonRequestUserLimit.last + maxCount = keyboardButtonRequestUserLimit.last, + requestName = true, + requestUsername = true, + requestPhoto = true ) requestBotsButton( "\uD83E\uDD16", requestIdBots, - maxCount = keyboardButtonRequestUserLimit.last + maxCount = keyboardButtonRequestUserLimit.last, + requestName = true, + requestUsername = true, + requestPhoto = true ) } row { requestChatButton( "\uD83D\uDDE3/\uD83D\uDC65", - requestIdAnyChat + requestIdAnyChat, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) } row { requestChatButton( "\uD83D\uDDE3", requestIdChannel, - isChannel = true + isChannel = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestChatButton( "\uD83D\uDDE3\uD83D\uDD17", requestIdPublicChannel, isChannel = true, - isPublic = true + isPublic = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestChatButton( "\uD83D\uDDE3❌\uD83D\uDD17", requestIdPrivateChannel, isChannel = true, - isPublic = false + isPublic = false, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestChatButton( "\uD83D\uDDE3\uD83D\uDC6E", requestIdChannelUserOwner, isChannel = true, - isOwnedBy = true + isOwnedBy = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) } row { requestGroupButton( "👥", - requestIdGroup + requestIdGroup, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestGroupButton( "👥\uD83D\uDD17", requestIdPublicGroup, - isPublic = true + isPublic = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestGroupButton( "👥❌\uD83D\uDD17", requestIdPrivateGroup, - isPublic = false + isPublic = false, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestGroupButton( "👥\uD83D\uDC6E", requestIdGroupUserOwner, - isOwnedBy = true + isOwnedBy = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) } row { requestGroupButton( "🏛", requestIdForum, - isForum = true + isForum = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestGroupButton( "🏛\uD83D\uDD17", requestIdPublicForum, isPublic = true, - isForum = true + isForum = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestGroupButton( "🏛❌\uD83D\uDD17", requestIdPrivateForum, isPublic = false, - isForum = true + isForum = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) requestGroupButton( "🏛\uD83D\uDC6E", requestIdForumUserOwner, isOwnedBy = true, - isForum = true + isForum = true, + requestTitle = true, + requestUsername = true, + requestPhoto = true ) } }