TelegramBotAPI-examples/PollsBot/src/main/kotlin/PollsBot.kt

180 lines
7.4 KiB
Kotlin
Raw Normal View History

2024-05-10 10:35:07 +00:00
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.LogLevel
import dev.inmo.kslog.common.defaultMessageFormatter
import dev.inmo.kslog.common.setDefaultKSLog
2023-08-19 20:30:18 +00:00
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
2024-05-10 10:35:07 +00:00
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.send.polls.sendQuizPoll
2023-08-19 20:30:18 +00:00
import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll
import dev.inmo.tgbotapi.extensions.api.send.send
2023-08-19 20:30:18 +00:00
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.onPollAnswer
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onPollUpdates
2024-05-10 10:35:07 +00:00
import dev.inmo.tgbotapi.extensions.utils.customEmojiTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgsSources
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.IdChatIdentifier
import dev.inmo.tgbotapi.types.PollId
import dev.inmo.tgbotapi.types.ReplyParameters
import dev.inmo.tgbotapi.types.polls.InputPollOption
import dev.inmo.tgbotapi.types.polls.PollAnswer
import dev.inmo.tgbotapi.utils.buildEntities
import dev.inmo.tgbotapi.utils.customEmoji
import dev.inmo.tgbotapi.utils.regular
import dev.inmo.tgbotapi.utils.underline
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
2023-08-19 20:30:18 +00:00
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
2024-05-10 10:35:07 +00:00
import kotlin.random.Random
2023-08-19 20:30:18 +00:00
/**
2023-08-20 05:38:56 +00:00
* This bot will answer with anonymous or public poll and send message on
* any update.
2023-08-20 05:38:56 +00:00
*
* * Use `/anonymous` to take anonymous regular poll
* * Use `/public` to take public regular poll
2023-08-19 20:30:18 +00:00
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
2024-05-10 10:35:07 +00:00
val isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
2023-08-19 20:30:18 +00:00
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
2024-03-18 07:46:15 +00:00
val pollToChat = mutableMapOf<PollId, IdChatIdentifier>()
2023-08-19 20:30:18 +00:00
val pollToChatMutex = Mutex()
2024-05-10 10:35:07 +00:00
onCommand("anonymous", requireOnlyCommandInMessage = false) {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "anonymous" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
2023-08-19 20:30:18 +00:00
val sentPoll = sendRegularPoll(
2024-05-10 10:35:07 +00:00
it.chat.id,
buildEntities {
regular("Test regular anonymous poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
2023-08-19 20:30:18 +00:00
(1 .. 10).map {
2024-05-10 10:35:07 +00:00
InputPollOption {
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
2023-08-19 20:30:18 +00:00
},
isAnonymous = true,
2024-01-08 07:21:41 +00:00
replyParameters = ReplyParameters(it)
2023-08-19 20:30:18 +00:00
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
}
}
2024-05-10 10:35:07 +00:00
onCommand("public", requireOnlyCommandInMessage = false) {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "public" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
2023-08-19 20:30:18 +00:00
val sentPoll = sendRegularPoll(
2024-05-10 10:35:07 +00:00
it.chat.id,
buildEntities {
regular("Test regular non anonymous poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
2023-08-19 20:30:18 +00:00
(1 .. 10).map {
2024-05-10 10:35:07 +00:00
InputPollOption {
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
2023-08-19 20:30:18 +00:00
},
isAnonymous = false,
2024-01-08 07:21:41 +00:00
replyParameters = ReplyParameters(it)
2023-08-19 20:30:18 +00:00
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
}
}
2024-05-10 10:35:07 +00:00
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)
}
},
2024-05-10 10:35:07 +00:00
(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)
}
2024-05-10 10:35:07 +00:00
}
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
}
}
2023-08-19 20:30:18 +00:00
onPollAnswer {
val chatId = pollToChat[it.pollId] ?: return@onPollAnswer
when(it) {
2023-08-20 08:30:55 +00:00
is PollAnswer.Public -> send(chatId, "[onPollAnswer] User ${it.user} have answered")
is PollAnswer.Anonymous -> send(chatId, "[onPollAnswer] Chat ${it.voterChat} have answered")
}
}
onPollUpdates {
val chatId = pollToChat[it.id] ?: return@onPollUpdates
when(it.isAnonymous) {
false -> send(chatId, "[onPollUpdates] Public poll updated: ${it.options.joinToString()}")
true -> send(chatId, "[onPollUpdates] Anonymous poll updated: ${it.options.joinToString()}")
2023-08-19 20:30:18 +00:00
}
}
2024-05-10 10:35:07 +00:00
setMyCommands(
BotCommand("anonymous", "Create anonymous regular poll"),
BotCommand("public", "Create non anonymous regular poll"),
BotCommand("quiz", "Create quiz poll with random right answer"),
)
2023-08-19 20:30:18 +00:00
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) }
}.second.join()
}