Compare commits

..

12 Commits

12 changed files with 373 additions and 66 deletions

9
BoostsInfoBot/README.md Normal file
View File

@@ -0,0 +1,9 @@
# UserChatShared
Showing info about boosts
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

View File

@@ -0,0 +1,21 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="BoostsInfoKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,65 @@
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.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.get.getUserChatBoosts
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatBoostUpdated
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.types.chat.member.ChatCommonAdministratorRights
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.utils.regular
import korlibs.time.DateFormat
import korlibs.time.format
suspend fun main(args: Array<String>) {
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 requestChatId = RequestId(1)
val bot = telegramBot(args.first())
bot.buildBehaviourWithLongPolling (defaultExceptionsHandler = { it.printStackTrace() }) {
onChatBoostUpdated {
println(it)
}
onCommand("start") {
reply(
it,
replyMarkup = flatReplyKeyboard {
requestChannelButton(
"Click me :)",
requestChatId,
botIsMember = true
)
}
) {
regular("Select chat to get know about your boosts")
}
}
onChatShared(initialFilter = { it.chatEvent.requestId == requestChatId }) {
val boosts = getUserChatBoosts(it.chatEvent.chatId, it.chat.id)
reply(
it
) {
boosts.boosts.forEach {
regular("Boost added: ${DateFormat.FORMAT1.format(it.addDate.asDate)}; Boost expire: ${DateFormat.FORMAT1.format(it.expirationDate.asDate)}; Unformatted: $it") + "\n"
}
}
}
}.join()
}

View File

@@ -0,0 +1,9 @@
# ReactionsInfoBot
This bot will resend messages with links with all variants of `LinkPreviewOptions`
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

View File

@@ -0,0 +1,21 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="LinkPreviewsBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,93 @@
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.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.copyMessage
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.api.send.setMessageReaction
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionUpdatedByUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionsCountUpdated
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.textLinkTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.uRLTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.LinkPreviewOptions
import dev.inmo.tgbotapi.types.chat.ExtendedChat
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.TextedContent
import dev.inmo.tgbotapi.types.reactions.Reaction
import dev.inmo.tgbotapi.utils.customEmoji
import dev.inmo.tgbotapi.utils.regular
/**
* This bot will reply with the same
*/
suspend fun main(vararg args: String) {
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)
bot.buildBehaviourWithLongPolling {
onContentMessage {
val url = it.withContentOrNull<TextedContent>() ?.let {
it.content.textSources.firstNotNullOfOrNull {
it.textLinkTextSourceOrNull() ?.url ?: it.uRLTextSourceOrNull() ?.source
}
} ?: null.apply {
reply(it) {
regular("I am support only content with text contains url only")
}
} ?: return@onContentMessage
it.withContentOrNull<TextedContent>() ?.let {
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Disabled
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Large(url, showAboveText = true)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Large(url, showAboveText = false)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Small(url, showAboveText = true)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Small(url, showAboveText = false)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Default(url, showAboveText = true)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Default(url, showAboveText = false)
)
}
}
}.join()
}

View File

@@ -1,16 +1,17 @@
import dev.inmo.kslog.common.KSLog import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.LogLevel import dev.inmo.kslog.common.LogLevel
import dev.inmo.kslog.common.defaultMessageFormatter import dev.inmo.kslog.common.defaultMessageFormatter
import dev.inmo.kslog.common.filter.filtered
import dev.inmo.kslog.common.setDefaultKSLog import dev.inmo.kslog.common.setDefaultKSLog
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.setMessageReaction
import dev.inmo.tgbotapi.extensions.api.send.setMessageReactions
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionUpdatedByUser import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionUpdatedByUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionsCountUpdated
import dev.inmo.tgbotapi.types.chat.ExtendedChat
import dev.inmo.tgbotapi.types.reactions.Reaction import dev.inmo.tgbotapi.types.reactions.Reaction
import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
import dev.inmo.tgbotapi.utils.customEmoji import dev.inmo.tgbotapi.utils.customEmoji
import dev.inmo.tgbotapi.utils.regular import dev.inmo.tgbotapi.utils.regular
@@ -33,10 +34,15 @@ suspend fun main(vararg args: String) {
bot.buildBehaviourWithLongPolling { bot.buildBehaviourWithLongPolling {
onChatMessageReactionUpdatedByUser { onChatMessageReactionUpdatedByUser {
val result = reply( setMessageReaction(
it.chat.id, it.chat.id,
it.messageId, it.messageId,
replyInChat = it.reactedUser.id ""
)
val replyResult = reply(
it.chat.id,
it.messageId,
replyInChatId = it.reactedUser.id
) { ) {
regular("Current reactions for message in reply:\n") regular("Current reactions for message in reply:\n")
it.new.forEach { it.new.forEach {
@@ -48,7 +54,15 @@ suspend fun main(vararg args: String) {
regular("\n") regular("\n")
} }
} }
println(result) setMessageReaction(
it.chat.id,
it.messageId,
)
}
onChatMessageReactionsCountUpdated {
val extendedChat: ExtendedChat = getChat(it.chat)
println(extendedChat)
println(it)
} }
}.join() }.join()
} }

View File

@@ -24,6 +24,7 @@ import dev.inmo.tgbotapi.types.chat.ChatPermissions
import dev.inmo.tgbotapi.types.chat.PublicChat import dev.inmo.tgbotapi.types.chat.PublicChat
import dev.inmo.tgbotapi.types.chat.member.* import dev.inmo.tgbotapi.types.chat.member.*
import dev.inmo.tgbotapi.types.commands.BotCommandScope import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.message.abstracts.AccessibleMessage
import dev.inmo.tgbotapi.types.request.RequestId import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.*
import dev.inmo.tgbotapi.utils.mention import dev.inmo.tgbotapi.utils.mention
@@ -185,14 +186,21 @@ suspend fun main(args: Array<String>) {
) { ) {
onCommand( onCommand(
"simple", "simple",
initialFilter = { it.chat is PublicChat && it.fromUserMessageOrNull()?.user?.id == allowedAdmin }) { initialFilter = { it.chat is PublicChat && it.fromUserMessageOrNull()?.user?.id == allowedAdmin }
) {
val replyMessage = it.replyTo val replyMessage = it.replyTo
val userInReply = replyMessage?.fromUserMessageOrNull()?.user?.id ?: return@onCommand val userInReply = replyMessage?.fromUserMessageOrNull()?.user?.id ?: return@onCommand
reply( if (replyMessage is AccessibleMessage) {
replyMessage, reply(
"Manage keyboard:", replyMessage,
replyMarkup = buildCommonKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand "Manage keyboard:",
) replyMarkup = buildCommonKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
)
} else {
reply(it) {
regular("Reply to somebody's message to get hist/her rights keyboard")
}
}
} }
onCommand( onCommand(
"granular", "granular",
@@ -204,11 +212,17 @@ suspend fun main(args: Array<String>) {
val usernameInText = it.content.textSources.firstNotNullOfOrNull { it.mentionTextSourceOrNull() } ?.username val usernameInText = it.content.textSources.firstNotNullOfOrNull { it.mentionTextSourceOrNull() } ?.username
val userInReply = replyMessage?.fromUserMessageOrNull()?.user?.id ?: return@onCommand val userInReply = replyMessage?.fromUserMessageOrNull()?.user?.id ?: return@onCommand
reply( if (replyMessage is AccessibleMessage) {
replyMessage, reply(
"Manage keyboard:", replyMessage,
replyMarkup = buildGranularKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand "Manage keyboard:",
) replyMarkup = buildGranularKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
)
} else {
reply(it) {
regular("Reply to somebody's message to get hist/her rights keyboard")
}
}
} }
onMessageDataCallbackQuery( onMessageDataCallbackQuery(

View File

@@ -7,14 +7,11 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPoll
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUserShared import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUserShared
import dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUsersShared
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestBotButton import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestChatButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestGroupButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestUserButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestUserOrBotButton
import dev.inmo.tgbotapi.types.BotCommand import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.chat.PrivateChat import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.keyboardButtonRequestUserLimit
import dev.inmo.tgbotapi.types.message.textsources.mention import dev.inmo.tgbotapi.types.message.textsources.mention
import dev.inmo.tgbotapi.types.request.RequestId import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.utils.row import dev.inmo.tgbotapi.utils.row
@@ -30,52 +27,90 @@ suspend fun main(args: Array<String>) {
val requestIdUserPremium = RequestId(3) val requestIdUserPremium = RequestId(3)
val requestIdBot = RequestId(4) val requestIdBot = RequestId(4)
val requestIdAnyChat = RequestId(5) val requestIdUsersOrBots = RequestId(5)
val requestIdChannel = RequestId(6) val requestIdUsersNonPremium = RequestId(6)
val requestIdPublicChannel = RequestId(7) val requestIdUsersAny = RequestId(7)
val requestIdPrivateChannel = RequestId(8) val requestIdUsersPremium = RequestId(8)
val requestIdChannelUserOwner = RequestId(9) val requestIdBots = RequestId(9)
val requestIdGroup = RequestId(10) val requestIdAnyChat = RequestId(10)
val requestIdPublicGroup = RequestId(11) val requestIdChannel = RequestId(11)
val requestIdPrivateGroup = RequestId(12) val requestIdPublicChannel = RequestId(12)
val requestIdGroupUserOwner = RequestId(13) val requestIdPrivateChannel = RequestId(13)
val requestIdChannelUserOwner = RequestId(14)
val requestIdForum = RequestId(14) val requestIdGroup = RequestId(15)
val requestIdPublicForum = RequestId(15) val requestIdPublicGroup = RequestId(16)
val requestIdPrivateForum = RequestId(16) val requestIdPrivateGroup = RequestId(17)
val requestIdForumUserOwner = RequestId(17) val requestIdGroupUserOwner = RequestId(18)
val requestIdForum = RequestId(19)
val requestIdPublicForum = RequestId(20)
val requestIdPrivateForum = RequestId(21)
val requestIdForumUserOwner = RequestId(22)
val keyboard = replyKeyboard( val keyboard = replyKeyboard(
resizeKeyboard = true, resizeKeyboard = true,
) { ) {
row { row {
requestUserOrBotButton( requestUserOrBotButton(
"\uD83D\uDC64/\uD83E\uDD16", "\uD83D\uDC64/\uD83E\uDD16 (1)",
requestIdUserOrBot requestIdUserOrBot
) )
} }
row { row {
requestUserButton( requestUserButton(
"\uD83D\uDC64", "\uD83D\uDC64 (1)",
requestIdUserNonPremium, requestIdUserNonPremium,
premiumUser = false premiumUser = false
) )
requestUserButton( requestUserButton(
"\uD83D\uDC64", "\uD83D\uDC64 (1)",
requestIdUserAny, requestIdUserAny,
premiumUser = null premiumUser = null
) )
requestUserButton( requestUserButton(
"\uD83D\uDC64", "\uD83D\uDC64 (1)",
requestIdUserPremium, requestIdUserPremium,
premiumUser = true premiumUser = true
) )
requestBotButton( requestBotButton(
"\uD83E\uDD16", "\uD83E\uDD16 (1)",
requestIdBot requestIdBot
) )
} }
row {
requestUsersOrBotsButton(
"\uD83D\uDC64/\uD83E\uDD16",
requestIdUsersOrBots,
maxCount = keyboardButtonRequestUserLimit.last
)
}
row {
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersNonPremium,
premiumUser = false,
maxCount = keyboardButtonRequestUserLimit.last
)
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersAny,
premiumUser = null,
maxCount = keyboardButtonRequestUserLimit.last
)
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersPremium,
premiumUser = true,
maxCount = keyboardButtonRequestUserLimit.last
)
requestBotsButton(
"\uD83E\uDD16",
requestIdBots,
maxCount = keyboardButtonRequestUserLimit.last
)
}
row { row {
requestChatButton( requestChatButton(
"\uD83D\uDDE3/\uD83D\uDC65", "\uD83D\uDDE3/\uD83D\uDC65",
@@ -164,25 +199,26 @@ suspend fun main(args: Array<String>) {
) )
} }
onUserShared { onUsersShared {
val userId = it.chatEvent.userId it.chatEvent.userIds.forEach { userId ->
val userInfo = runCatchingSafely { getChat(userId) }.getOrNull() val userInfo = runCatchingSafely { getChat(userId) }.getOrNull()
reply( reply(
it, it,
) { ) {
+"You have shared " +"You have shared "
+mention( +mention(
when (it.chatEvent.requestId) { when (it.chatEvent.requestId) {
requestIdUserOrBot -> "user or bot" requestIdUserOrBot -> "user or bot"
requestIdUserNonPremium -> "non premium user" requestIdUserNonPremium -> "non premium user"
requestIdUserAny -> "any user" requestIdUserAny -> "any user"
requestIdUserPremium -> "premium user" requestIdUserPremium -> "premium user"
requestIdBot -> "bot" requestIdBot -> "bot"
else -> "somebody O.o" else -> "somebody O.o"
}, },
userId userId
) )
+" (user info: $userInfo; user id: $userId)" +" (user info: $userInfo; user id: $userId)"
}
} }
} }

View File

@@ -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.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.ktor.server.createKtorServer import dev.inmo.micro_utils.ktor.server.createKtorServer
import dev.inmo.tgbotapi.extensions.api.answers.answer import dev.inmo.tgbotapi.extensions.api.answers.answer
@@ -14,6 +18,7 @@ import dev.inmo.tgbotapi.requests.answers.InlineQueryResultsButton
import dev.inmo.tgbotapi.types.BotCommand import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent
import dev.inmo.tgbotapi.types.LinkPreviewOptions
import dev.inmo.tgbotapi.types.webAppQueryIdField import dev.inmo.tgbotapi.types.webAppQueryIdField
import dev.inmo.tgbotapi.types.webapps.WebAppInfo import dev.inmo.tgbotapi.types.webapps.WebAppInfo
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.*
@@ -43,6 +48,16 @@ suspend fun main(vararg args: String) {
args.first(), args.first(),
testServer = args.any { it == "testServer" } testServer = args.any { it == "testServer" }
) )
val isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val bot = telegramBot(telegramBotAPIUrlsKeeper) val bot = telegramBot(telegramBotAPIUrlsKeeper)
createKtorServer( createKtorServer(
"0.0.0.0", "0.0.0.0",
@@ -102,8 +117,11 @@ suspend fun main(vararg args: String) {
row { row {
webAppButton("Open WebApp", WebAppInfo(args[1])) webAppButton("Open WebApp", WebAppInfo(args[1]))
} }
} },
linkPreviewOptions = LinkPreviewOptions.Small(
args[1],
showAboveText = false
)
) )
} }
onCommand("attachment_menu") { onCommand("attachment_menu") {
@@ -114,8 +132,11 @@ suspend fun main(vararg args: String) {
row { row {
webAppButton("Open WebApp", WebAppInfo(args[1])) webAppButton("Open WebApp", WebAppInfo(args[1]))
} }
} },
linkPreviewOptions = LinkPreviewOptions.Large(
args[1],
showAboveText = true
)
) )
} }
onBaseInlineQuery { onBaseInlineQuery {

View File

@@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx2344m
kotlin_version=1.9.22 kotlin_version=1.9.22
telegram_bot_api_version=10.0.0-branch_10.0.0-build2034 telegram_bot_api_version=10.0.0
micro_utils_version=0.20.25 micro_utils_version=0.20.26
serialization_version=1.6.2 serialization_version=1.6.2
ktor_version=2.3.7 ktor_version=2.3.7

View File

@@ -43,3 +43,7 @@ include ":StickerSetHandler"
include ":InlineQueriesBot" include ":InlineQueriesBot"
include ":ReactionsInfoBot" include ":ReactionsInfoBot"
include ":LinkPreviewsBot"
include ":BoostsInfoBot"