Compare commits

..

1 Commits

Author SHA1 Message Date
cde935eef9 Merge 984ffb8bae into 3609ae6bc2 2024-01-10 10:47:36 +00:00
25 changed files with 154 additions and 698 deletions

View File

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

View File

@@ -1,21 +0,0 @@
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

@@ -1,65 +0,0 @@
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

@@ -1,9 +0,0 @@
# BusinessConnectionBotBot
When bot connected or disconnected to the business chat, it will notify this chat
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

View File

@@ -1,21 +0,0 @@
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"
}

View File

@@ -1,85 +0,0 @@
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<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 businessConnectionsChats = mutableMapOf<BusinessConnectionId, ChatId>()
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()
}

View File

@@ -1,9 +0,0 @@
# CustomBot
This bot basically have no any useful behaviour, but you may customize it as a playground
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

View File

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

View File

@@ -1,33 +0,0 @@
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.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.utils.PreviewFeature
import kotlinx.coroutines.*
/**
* The main purpose of this bot is just to answer "Oh, hi, " and add user mention here
*/
@OptIn(PreviewFeature::class)
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
val me = getMe()
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) }
}.second.join()
}

View File

@@ -1,16 +1,13 @@
import dev.inmo.micro_utils.coroutines.AccumulatorFlow 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.micro_utils.fsm.common.State
import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.api.send.sendMessage import dev.inmo.tgbotapi.extensions.api.send.sendMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.* import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
import dev.inmo.tgbotapi.extensions.utils.extensions.sameThread import dev.inmo.tgbotapi.extensions.utils.extensions.sameThread
import dev.inmo.tgbotapi.extensions.utils.formatting.* 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.IdChatIdentifier
import dev.inmo.tgbotapi.types.MessageThreadId import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
@@ -57,8 +54,7 @@ suspend fun main(args: Array<String>) {
val content = contentMessage.content val content = contentMessage.content
when { when {
content is TextContent && content.text == "/stop" content is TextContent && content.parseCommandsWithParams().keys.contains("stop") -> StopState(it.context)
|| content is TextContent && content.parseCommandsWithArgs().keys.contains("stop") -> StopState(it.context)
else -> { else -> {
execute(content.createResend(it.context)) execute(content.createResend(it.context))
it it
@@ -76,17 +72,5 @@ suspend fun main(args: Array<String>) {
) { ) {
startChain(ExpectContentOrStopState(it.chat.id, it)) 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() }.second.join()
} }

View File

@@ -56,10 +56,6 @@ suspend fun main(vararg args: String) {
} ?: chat.title } ?: 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() is UnknownChatType -> "Unknown :(".escapeMarkdownV2Common()
} }
reply( reply(

View File

@@ -9,7 +9,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onDeepLi
import dev.inmo.tgbotapi.requests.answers.InlineQueryResultsButton import dev.inmo.tgbotapi.requests.answers.InlineQueryResultsButton
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.InlineQueryId
import dev.inmo.tgbotapi.types.inlineQueryAnswerResultsLimit import dev.inmo.tgbotapi.types.inlineQueryAnswerResultsLimit
import dev.inmo.tgbotapi.utils.buildEntities import dev.inmo.tgbotapi.utils.buildEntities
@@ -32,9 +31,9 @@ suspend fun doInlineQueriesBot(token: String) {
answer( answer(
it, it,
results = results.map { resultNumber -> results = results.map { resultNumber ->
val inlineQueryId = InlineQueryId(resultNumber.toString()) val resultAsString = resultNumber.toString()
InlineQueryResultArticle( InlineQueryResultArticle(
inlineQueryId, resultAsString,
"Title $resultNumber", "Title $resultNumber",
InputTextMessageContent( InputTextMessageContent(
buildEntities { buildEntities {

View File

@@ -15,7 +15,6 @@ import dev.inmo.tgbotapi.extensions.utils.withContent
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.InlineQueryId
import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -138,7 +137,7 @@ suspend fun activateKeyboardsBot(
it, it,
results = listOf( results = listOf(
InlineQueryResultArticle( InlineQueryResultArticle(
InlineQueryId(it.query), it.query,
"Send buttons", "Send buttons",
InputTextMessageContent("It is sent via inline mode inline buttons"), InputTextMessageContent("It is sent via inline mode inline buttons"),
replyMarkup = inlineKeyboard { replyMarkup = inlineKeyboard {

View File

@@ -1,16 +1,33 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.EditLiveLocationInfo import dev.inmo.tgbotapi.extensions.api.EditLiveLocationInfo
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.edit.edit
import dev.inmo.tgbotapi.extensions.api.edit.location.live.stopLiveLocation import dev.inmo.tgbotapi.extensions.api.edit.location.live.stopLiveLocation
import dev.inmo.tgbotapi.extensions.api.handleLiveLocation import dev.inmo.tgbotapi.extensions.api.handleLiveLocation
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitMessageDataCallbackQuery import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitMessageDataCallbackQuery
import dev.inmo.tgbotapi.extensions.behaviour_builder.oneOf
import dev.inmo.tgbotapi.extensions.behaviour_builder.parallel
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling 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.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.ifFromChannelGroupContentMessage
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
import dev.inmo.tgbotapi.types.chat.*
import dev.inmo.tgbotapi.types.chat.GroupChat
import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.chat.SupergroupChat
import dev.inmo.tgbotapi.types.location.LiveLocation import dev.inmo.tgbotapi.types.location.LiveLocation
import dev.inmo.tgbotapi.types.message.MarkdownV2
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.LiveLocationContent
import dev.inmo.tgbotapi.types.message.content.LocationContent import dev.inmo.tgbotapi.types.message.content.LocationContent
import dev.inmo.tgbotapi.utils.PreviewFeature
import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@@ -47,7 +64,7 @@ suspend fun main(vararg args: String) {
handleLiveLocation( handleLiveLocation(
it.chat.id, it.chat.id,
locationsFlow, locationsFlow,
sentMessageFlow = FlowCollector { currentMessageState.emit(it) }, sentMessageFlow = FlowCollector { currentMessageState.emit(it) }
) )
} }

View File

@@ -1,37 +1,34 @@
import com.benasher44.uuid.uuid4 import com.benasher44.uuid.uuid4
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.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
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.* import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.send.polls.sendQuizPoll
import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.customEmojiTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgsSources
import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sender_chat import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sender_chat
import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2 import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2 import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.ifChannelChat import dev.inmo.tgbotapi.extensions.utils.ifChannelChat
import dev.inmo.tgbotapi.extensions.utils.ifFromChannelGroupContentMessage import dev.inmo.tgbotapi.extensions.utils.ifFromChannelGroupContentMessage
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.IdChatIdentifier
import dev.inmo.tgbotapi.types.PollIdentifier
import dev.inmo.tgbotapi.types.ReplyParameters
import dev.inmo.tgbotapi.types.chat.* import dev.inmo.tgbotapi.types.chat.*
import dev.inmo.tgbotapi.types.chat.GroupChat import dev.inmo.tgbotapi.types.chat.GroupChat
import dev.inmo.tgbotapi.types.chat.PrivateChat import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.chat.SupergroupChat import dev.inmo.tgbotapi.types.chat.SupergroupChat
import dev.inmo.tgbotapi.types.message.MarkdownV2 import dev.inmo.tgbotapi.types.message.MarkdownV2
import dev.inmo.tgbotapi.types.polls.* import dev.inmo.tgbotapi.types.polls.Poll
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.types.polls.PollAnswer
import dev.inmo.tgbotapi.types.polls.PollOption
import dev.inmo.tgbotapi.types.polls.RegularPoll
import dev.inmo.tgbotapi.utils.PreviewFeature
import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlin.random.Random
/** /**
* This bot will answer with anonymous or public poll and send message on * This bot will answer with anonymous or public poll and send message on
@@ -43,43 +40,19 @@ import kotlin.random.Random
@OptIn(PreviewFeature::class) @OptIn(PreviewFeature::class)
suspend fun main(vararg args: String) { suspend fun main(vararg args: String) {
val botToken = args.first() val botToken = args.first()
val isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) { telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
val me = getMe() val me = getMe()
val pollToChat = mutableMapOf<PollId, IdChatIdentifier>() val pollToChat = mutableMapOf<PollIdentifier, IdChatIdentifier>()
val pollToChatMutex = Mutex() val pollToChatMutex = Mutex()
onCommand("anonymous", requireOnlyCommandInMessage = false) { onCommand("anonymous") {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "anonymous" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
val sentPoll = sendRegularPoll( val sentPoll = sendRegularPoll(
it.chat.id, it.chat,
buildEntities { "Test regular anonymous poll",
regular("Test regular anonymous poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
(1 .. 10).map { (1 .. 10).map {
InputPollOption { it.toString()
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
}, },
isAnonymous = true, isAnonymous = true,
replyParameters = ReplyParameters(it) replyParameters = ReplyParameters(it)
@@ -89,27 +62,12 @@ suspend fun main(vararg args: String) {
} }
} }
onCommand("public", requireOnlyCommandInMessage = false) { onCommand("public") {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "public" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
val sentPoll = sendRegularPoll( val sentPoll = sendRegularPoll(
it.chat.id, it.chat,
buildEntities { "Test regular anonymous poll",
regular("Test regular non anonymous poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
(1 .. 10).map { (1 .. 10).map {
InputPollOption { it.toString()
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
}, },
isAnonymous = false, isAnonymous = false,
replyParameters = ReplyParameters(it) replyParameters = ReplyParameters(it)
@@ -119,44 +77,6 @@ suspend fun main(vararg args: String) {
} }
} }
onCommand("quiz", requireOnlyCommandInMessage = false) {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "quiz" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
val correctAnswer = Random.nextInt(10)
val sentPoll = sendQuizPoll(
it.chat.id,
questionEntities = buildEntities {
regular("Test quiz poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
(1 .. 10).map {
InputPollOption {
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
},
isAnonymous = false,
replyParameters = ReplyParameters(it),
correctOptionId = correctAnswer,
explanationTextSources = buildEntities {
regular("Random solved it to be ") + underline((correctAnswer + 1).toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
}
}
onPollAnswer { onPollAnswer {
val chatId = pollToChat[it.pollId] ?: return@onPollAnswer val chatId = pollToChat[it.pollId] ?: return@onPollAnswer
@@ -175,12 +95,6 @@ suspend fun main(vararg args: String) {
} }
} }
setMyCommands(
BotCommand("anonymous", "Create anonymous regular poll"),
BotCommand("public", "Create non anonymous regular poll"),
BotCommand("quiz", "Create quiz poll with random right answer"),
)
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) } allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) }
}.second.join() }.second.join()
} }

View File

@@ -42,7 +42,7 @@ suspend fun main(vararg args: String) {
val replyResult = reply( val replyResult = reply(
it.chat.id, it.chat.id,
it.messageId, it.messageId,
replyInChatId = it.reactedUser.id replyInChat = 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 {

View File

@@ -7,11 +7,9 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.possiblyWithEffectMessageOrNull
import dev.inmo.tgbotapi.extensions.utils.shortcuts.* import dev.inmo.tgbotapi.extensions.utils.shortcuts.*
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.ReplyParameters 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.message.content.TextContent
import dev.inmo.tgbotapi.types.quoteEntitiesField import dev.inmo.tgbotapi.types.quoteEntitiesField
import dev.inmo.tgbotapi.utils.extensions.threadIdOrNull import dev.inmo.tgbotapi.utils.extensions.threadIdOrNull
@@ -24,7 +22,6 @@ suspend fun activateResenderBot(
telegramBotWithBehaviourAndLongPolling(token, scope = CoroutineScope(currentCoroutineContext() + SupervisorJob())) { telegramBotWithBehaviourAndLongPolling(token, scope = CoroutineScope(currentCoroutineContext() + SupervisorJob())) {
onContentMessage( onContentMessage(
subcontextUpdatesFilter = MessageFilterByChat, subcontextUpdatesFilter = MessageFilterByChat,
initialFilter = { it !is BusinessContentMessage<*> || !it.sentByBusinessConnectionOwner }
) { ) {
val chat = it.chat val chat = it.chat
@@ -40,8 +37,7 @@ suspend fun activateResenderBot(
entities = quote ?.textSources ?: emptyList(), entities = quote ?.textSources ?: emptyList(),
quotePosition = quote ?.position quotePosition = quote ?.position
) )
}, }
effectId = it.possiblyWithEffectMessageOrNull() ?.effectId
) )
) { ) {
it.forEach(print) it.forEach(print)

View File

@@ -1,9 +1,4 @@
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.firstOf import dev.inmo.micro_utils.coroutines.firstOf
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.fsm.common.State import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
@@ -29,7 +24,6 @@ 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
@@ -55,19 +49,9 @@ sealed interface UserRetrievingStep : State {
suspend fun main(args: Array<String>) { suspend fun main(args: Array<String>) {
val botToken = args.first() val botToken = args.first()
val isDebug = args.getOrNull(2) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val bot = telegramBot(botToken) val bot = telegramBot(botToken)
val allowedAdmin = ChatId(RawChatId(args[1].toLong())) val allowedAdmin = ChatId(args[1].toLong())
fun Boolean?.allowedSymbol() = when (this) { fun Boolean?.allowedSymbol() = when (this) {
true -> "" true -> ""
@@ -201,21 +185,14 @@ 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
if (replyMessage is AccessibleMessage) { reply(
reply( replyMessage,
replyMessage, "Manage keyboard:",
"Manage keyboard:", replyMarkup = buildCommonKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
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",
@@ -227,17 +204,11 @@ 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
if (replyMessage is AccessibleMessage) { reply(
reply( replyMessage,
replyMessage, "Manage keyboard:",
"Manage keyboard:", replyMarkup = buildGranularKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
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(
@@ -377,8 +348,8 @@ suspend fun main(args: Array<String>) {
initialFilter = { it.user.id == allowedAdmin } initialFilter = { it.user.id == allowedAdmin }
) { ) {
val (channelIdString, userIdString) = it.data.split(" ").drop(1) val (channelIdString, userIdString) = it.data.split(" ").drop(1)
val channelId = ChatId(RawChatId(channelIdString.toLong())) val channelId = ChatId(channelIdString.toLong())
val userId = ChatId(RawChatId(userIdString.toLong())) val userId = ChatId(userIdString.toLong())
val chatMember = getChatMember(channelId, userId) val chatMember = getChatMember(channelId, userId)
val asAdmin = chatMember.administratorChatMemberOrNull() val asAdmin = chatMember.administratorChatMemberOrNull()
val asMember = chatMember.memberChatMemberOrNull() val asMember = chatMember.memberChatMemberOrNull()
@@ -532,9 +503,5 @@ suspend fun main(args: Array<String>) {
BotCommand("rights_in_channel", "Trigger granular keyboard. Use with reply to user"), BotCommand("rights_in_channel", "Trigger granular keyboard. Use with reply to user"),
scope = BotCommandScope.AllGroupChats scope = BotCommandScope.AllGroupChats
) )
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.join() }.join()
} }

View File

@@ -9,9 +9,16 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.types.StickerFormat import dev.inmo.tgbotapi.types.StickerFormat
import dev.inmo.tgbotapi.types.StickerType import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.message.textsources.* 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.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.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.RegularStickerSet
import dev.inmo.tgbotapi.types.stickers.RegularVideoStickerSet
import dev.inmo.tgbotapi.types.stickers.StickerSet import dev.inmo.tgbotapi.types.stickers.StickerSet
import dev.inmo.tgbotapi.types.stickers.UnknownStickerSet import dev.inmo.tgbotapi.types.stickers.UnknownStickerSet
import dev.inmo.tgbotapi.utils.bold import dev.inmo.tgbotapi.utils.bold
@@ -24,6 +31,12 @@ fun StickerSet?.buildInfo() = buildEntities {
} else { } else {
bold("StickerSet name: ") + "${name}\n" bold("StickerSet name: ") + "${name}\n"
bold("StickerSet title: ") + "${title}\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( bold(
when (stickerType) { when (stickerType) {
StickerType.CustomEmoji -> "Custom emoji" StickerType.CustomEmoji -> "Custom emoji"
@@ -31,7 +44,7 @@ fun StickerSet?.buildInfo() = buildEntities {
StickerType.Regular -> "Regular" StickerType.Regular -> "Regular"
is StickerType.Unknown -> "Unknown type \"${stickerType.type}\"" is StickerType.Unknown -> "Unknown type \"${stickerType.type}\""
} }
) + " sticker set with title " + bold(title) + " and name " + bold(name.string) ) + " sticker set with title " + bold(title) + " and name " + bold(name)
} }
} }

View File

@@ -1,5 +1,4 @@
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.files.downloadFile import dev.inmo.tgbotapi.extensions.api.files.downloadFile
import dev.inmo.tgbotapi.extensions.api.files.downloadFileToTemp import dev.inmo.tgbotapi.extensions.api.files.downloadFileToTemp
@@ -14,7 +13,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onSticke
import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sticker import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sticker
import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile
import dev.inmo.tgbotapi.requests.stickers.InputSticker import dev.inmo.tgbotapi.requests.stickers.InputSticker
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.chat.Chat import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.files.* import dev.inmo.tgbotapi.types.files.*
import dev.inmo.tgbotapi.types.toChatId import dev.inmo.tgbotapi.types.toChatId
@@ -34,7 +32,7 @@ suspend fun main(args: Array<String>) {
} }
) { ) {
val me = getMe() val me = getMe()
fun Chat.stickerSetName() = StickerSetName("s${id.chatId}_by_${me.username ?.withoutAt}") fun Chat.stickerSetName() = "s${id.chatId}_by_${me.username ?.usernameWithoutAt}"
onCommand("start") { onCommand("start") {
reply(it) { reply(it) {
botCommand("delete") + " - to clear stickers" botCommand("delete") + " - to clear stickers"
@@ -57,19 +55,16 @@ suspend fun main(args: Array<String>) {
val newSticker = when (sticker) { val newSticker = when (sticker) {
is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji( is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji(
downloadFileToTemp(sticker.fileId).asMultipartFile(), downloadFileToTemp(sticker.fileId).asMultipartFile(),
sticker.stickerFormat,
listOf(sticker.emoji ?: "\uD83D\uDE0A"), listOf(sticker.emoji ?: "\uD83D\uDE0A"),
emptyList() emptyList()
) )
is MaskSticker -> InputSticker.Mask( is MaskSticker -> InputSticker.Mask(
downloadFileToTemp(sticker.fileId).asMultipartFile(), downloadFileToTemp(sticker.fileId).asMultipartFile(),
sticker.stickerFormat,
listOf(sticker.emoji ?: "\uD83D\uDE0A"), listOf(sticker.emoji ?: "\uD83D\uDE0A"),
sticker.maskPosition sticker.maskPosition
) )
is RegularSticker -> InputSticker.WithKeywords.Regular( is RegularSticker -> InputSticker.WithKeywords.Regular(
downloadFileToTemp(sticker.fileId).asMultipartFile(), downloadFileToTemp(sticker.fileId).asMultipartFile(),
sticker.stickerFormat,
listOf(sticker.emoji ?: "\uD83D\uDE0A"), listOf(sticker.emoji ?: "\uD83D\uDE0A"),
emptyList() emptyList()
) )
@@ -78,25 +73,18 @@ suspend fun main(args: Array<String>) {
runCatchingSafely { runCatchingSafely {
getStickerSet(stickerSetName) getStickerSet(stickerSetName)
}.onSuccess { stickerSet -> }.onSuccess { stickerSet ->
runCatching { addStickerToSet(it.chat.id.toChatId(), stickerSet.name, newSticker).also { _ ->
addStickerToSet(it.chat.id.toChatId(), stickerSet.name, newSticker).also { _ ->
reply(
it,
getStickerSet(stickerSetName).stickers.last()
)
}
}.onFailure { exception ->
exception.printStackTrace()
reply( reply(
it, it,
"Unable to add sticker in stickerset" getStickerSet(stickerSetName).stickers.last()
) )
} }
}.onFailure { exception -> }.onFailure { _ ->
createNewStickerSet( createNewStickerSet(
it.chat.id.toChatId(), it.chat.id.toChatId(),
stickerSetName.string, stickerSetName,
"Sticker set by ${me.firstName}", "Sticker set by ${me.firstName}",
it.content.media.stickerFormat,
listOf( listOf(
newSticker newSticker
), ),
@@ -109,9 +97,5 @@ suspend fun main(args: Array<String>) {
} }
} }
} }
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.second.join() }.second.join()
} }

View File

@@ -1,7 +1,3 @@
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.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
@@ -11,26 +7,20 @@ 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.behaviour_builder.triggers_handling.onUsersShared import dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard
import dev.inmo.tgbotapi.extensions.utils.types.buttons.* import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestBotButton
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
suspend fun main(args: Array<String>) { suspend fun main(args: Array<String>) {
val botToken = args.first() 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) val bot = telegramBot(botToken)
@@ -40,234 +30,127 @@ suspend fun main(args: Array<String>) {
val requestIdUserPremium = RequestId(3) val requestIdUserPremium = RequestId(3)
val requestIdBot = RequestId(4) val requestIdBot = RequestId(4)
val requestIdUsersOrBots = RequestId(5) val requestIdAnyChat = RequestId(5)
val requestIdUsersNonPremium = RequestId(6) val requestIdChannel = RequestId(6)
val requestIdUsersAny = RequestId(7) val requestIdPublicChannel = RequestId(7)
val requestIdUsersPremium = RequestId(8) val requestIdPrivateChannel = RequestId(8)
val requestIdBots = RequestId(9) val requestIdChannelUserOwner = RequestId(9)
val requestIdAnyChat = RequestId(10) val requestIdGroup = RequestId(10)
val requestIdChannel = RequestId(11) val requestIdPublicGroup = RequestId(11)
val requestIdPublicChannel = RequestId(12) val requestIdPrivateGroup = RequestId(12)
val requestIdPrivateChannel = RequestId(13) val requestIdGroupUserOwner = RequestId(13)
val requestIdChannelUserOwner = RequestId(14)
val requestIdGroup = RequestId(15) val requestIdForum = RequestId(14)
val requestIdPublicGroup = RequestId(16) val requestIdPublicForum = RequestId(15)
val requestIdPrivateGroup = RequestId(17) val requestIdPrivateForum = RequestId(16)
val requestIdGroupUserOwner = RequestId(18) val requestIdForumUserOwner = RequestId(17)
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 (1)", "\uD83D\uDC64/\uD83E\uDD16",
requestIdUserOrBot, requestIdUserOrBot
requestName = true,
requestUsername = true,
requestPhoto = true
) )
} }
row { row {
requestUserButton( requestUserButton(
"\uD83D\uDC64 (1)", "\uD83D\uDC64",
requestIdUserNonPremium, requestIdUserNonPremium,
premiumUser = false, premiumUser = false
requestName = true,
requestUsername = true,
requestPhoto = true
) )
requestUserButton( requestUserButton(
"\uD83D\uDC64 (1)", "\uD83D\uDC64",
requestIdUserAny, requestIdUserAny,
premiumUser = null, premiumUser = null
requestName = true,
requestUsername = true,
requestPhoto = true
) )
requestUserButton( requestUserButton(
"\uD83D\uDC64 (1)", "\uD83D\uDC64",
requestIdUserPremium, requestIdUserPremium,
premiumUser = true, premiumUser = true
requestName = true,
requestUsername = true,
requestPhoto = true
) )
requestBotButton( requestBotButton(
"\uD83E\uDD16 (1)",
requestIdBot,
requestName = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestUsersOrBotsButton(
"\uD83D\uDC64/\uD83E\uDD16",
requestIdUsersOrBots,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersNonPremium,
premiumUser = false,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersAny,
premiumUser = null,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersPremium,
premiumUser = true,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestBotsButton(
"\uD83E\uDD16", "\uD83E\uDD16",
requestIdBots, requestIdBot
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
) )
} }
row { row {
requestChatButton( requestChatButton(
"\uD83D\uDDE3/\uD83D\uDC65", "\uD83D\uDDE3/\uD83D\uDC65",
requestIdAnyChat, requestIdAnyChat
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
} }
row { row {
requestChatButton( requestChatButton(
"\uD83D\uDDE3", "\uD83D\uDDE3",
requestIdChannel, requestIdChannel,
isChannel = true, isChannel = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestChatButton( requestChatButton(
"\uD83D\uDDE3\uD83D\uDD17", "\uD83D\uDDE3\uD83D\uDD17",
requestIdPublicChannel, requestIdPublicChannel,
isChannel = true, isChannel = true,
isPublic = true, isPublic = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestChatButton( requestChatButton(
"\uD83D\uDDE3\uD83D\uDD17", "\uD83D\uDDE3\uD83D\uDD17",
requestIdPrivateChannel, requestIdPrivateChannel,
isChannel = true, isChannel = true,
isPublic = false, isPublic = false
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestChatButton( requestChatButton(
"\uD83D\uDDE3\uD83D\uDC6E", "\uD83D\uDDE3\uD83D\uDC6E",
requestIdChannelUserOwner, requestIdChannelUserOwner,
isChannel = true, isChannel = true,
isOwnedBy = true, isOwnedBy = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
} }
row { row {
requestGroupButton( requestGroupButton(
"👥", "👥",
requestIdGroup, requestIdGroup
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestGroupButton( requestGroupButton(
"👥\uD83D\uDD17", "👥\uD83D\uDD17",
requestIdPublicGroup, requestIdPublicGroup,
isPublic = true, isPublic = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestGroupButton( requestGroupButton(
"👥❌\uD83D\uDD17", "👥❌\uD83D\uDD17",
requestIdPrivateGroup, requestIdPrivateGroup,
isPublic = false, isPublic = false
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestGroupButton( requestGroupButton(
"👥\uD83D\uDC6E", "👥\uD83D\uDC6E",
requestIdGroupUserOwner, requestIdGroupUserOwner,
isOwnedBy = true, isOwnedBy = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
} }
row { row {
requestGroupButton( requestGroupButton(
"🏛", "🏛",
requestIdForum, requestIdForum,
isForum = true, isForum = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestGroupButton( requestGroupButton(
"🏛\uD83D\uDD17", "🏛\uD83D\uDD17",
requestIdPublicForum, requestIdPublicForum,
isPublic = true, isPublic = true,
isForum = true, isForum = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestGroupButton( requestGroupButton(
"🏛❌\uD83D\uDD17", "🏛❌\uD83D\uDD17",
requestIdPrivateForum, requestIdPrivateForum,
isPublic = false, isPublic = false,
isForum = true, isForum = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
requestGroupButton( requestGroupButton(
"🏛\uD83D\uDC6E", "🏛\uD83D\uDC6E",
requestIdForumUserOwner, requestIdForumUserOwner,
isOwnedBy = true, isOwnedBy = true,
isForum = true, isForum = true
requestTitle = true,
requestUsername = true,
requestPhoto = true
) )
} }
} }
@@ -281,26 +164,25 @@ suspend fun main(args: Array<String>) {
) )
} }
onUsersShared { onUserShared {
it.chatEvent.userIds.forEach { userId -> val userId = it.chatEvent.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,4 +1,7 @@
import dev.inmo.kslog.common.* 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
@@ -15,7 +18,6 @@ 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.InlineQueryId
import dev.inmo.tgbotapi.types.LinkPreviewOptions 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
@@ -37,7 +39,6 @@ import java.nio.charset.Charset
* *
* * Telegram Token * * Telegram Token
* * URL where will be placed * * URL where will be placed
* * Port (default 8080)
* *
* Will start the server to share the static (index.html and WebApp.js) on 0.0.0.0:8080 * Will start the server to share the static (index.html and WebApp.js) on 0.0.0.0:8080
*/ */
@@ -56,7 +57,6 @@ suspend fun main(vararg args: String) {
} }
) )
} }
val initiationLogger = KSLog("Initialization")
val bot = telegramBot(telegramBotAPIUrlsKeeper) val bot = telegramBot(telegramBotAPIUrlsKeeper)
createKtorServer( createKtorServer(
@@ -68,34 +68,18 @@ suspend fun main(vararg args: String) {
) { ) {
routing { routing {
val baseJsFolder = File("WebApp/build/dist/js/") val baseJsFolder = File("WebApp/build/dist/js/")
val prodSubFolder = File(baseJsFolder, "productionExecutable") baseJsFolder.list() ?.forEach {
val devSubFolder = File(baseJsFolder, "developmentExecutable") if (it == "productionExecutable" || it == "developmentExecutable") {
staticFiles("", File(baseJsFolder, it)) {
val staticFolder = when { default("WebApp/build/dist/js/$it/index.html")
prodSubFolder.exists() -> { }
initiationLogger.i("Folder for static is ${prodSubFolder.absolutePath}")
prodSubFolder
} }
devSubFolder.exists() -> {
initiationLogger.i("Folder for static is ${devSubFolder.absolutePath}")
devSubFolder
}
else -> error("""
Unable to detect any folder with static. Current working directory: ${File("").absolutePath}.
Searched paths:
* ${prodSubFolder.absolutePath}
* ${devSubFolder.absolutePath}
""".trimIndent())
}
staticFiles("", staticFolder) {
default("${staticFolder.absolutePath}${File.separator}index.html")
} }
post("inline") { post("inline") {
val requestBody = call.receiveText() val requestBody = call.receiveText()
val queryId = call.parameters[webAppQueryIdField] ?.let(::InlineQueryId) ?: error("$webAppQueryIdField should be presented") val queryId = call.parameters[webAppQueryIdField] ?: error("$webAppQueryIdField should be presented")
bot.answerInlineQuery(queryId, listOf(InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody)))) bot.answer(queryId, InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody)))
call.respond(HttpStatusCode.OK) call.respond(HttpStatusCode.OK)
} }
post("check") { post("check") {

View File

@@ -4,8 +4,8 @@ org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2344m org.gradle.jvmargs=-Xmx2344m
kotlin_version=1.9.23 kotlin_version=1.9.22
telegram_bot_api_version=14.0.0 telegram_bot_api_version=10.0.0-branch_10.0.0-build2050
micro_utils_version=0.20.45 micro_utils_version=0.20.25
serialization_version=1.6.3 serialization_version=1.6.2
ktor_version=2.3.10 ktor_version=2.3.7

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip

View File

@@ -45,9 +45,3 @@ include ":InlineQueriesBot"
include ":ReactionsInfoBot" include ":ReactionsInfoBot"
include ":LinkPreviewsBot" include ":LinkPreviewsBot"
include ":BoostsInfoBot"
include ":BusinessConnectionsBot"
include ":CustomBot"