temporal progress

This commit is contained in:
2022-09-07 15:01:03 +06:00
parent 4a6e7e472b
commit 0b6f3aeb17
8 changed files with 210 additions and 24 deletions

View File

@@ -1,16 +1,30 @@
import dev.inmo.krontab.utils.asFlow
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
import dev.inmo.micro_utils.repos.cache.cached
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
import dev.inmo.micro_utils.repos.mappers.withMapper
import dev.inmo.micro_utils.repos.unset
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.delete
import dev.inmo.tgbotapi.extensions.api.send.media.*
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommandWithArgs
import dev.inmo.tgbotapi.requests.abstracts.FileUrl
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.ChannelChat
import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.media.TelegramMediaPhoto
import java.io.File
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.serialization.json.Json
import models.Config
@@ -35,28 +49,104 @@ suspend fun main(args: Array<String>) {
"configs"
).withMapper(
{ chatId },
{ json.encodeToString(ChatConfig.serializer(), this) },
{ json.encodeToString(ChatSettings.serializer(), this) },
{ ChatId(this) },
{ json.decodeFromString(ChatConfig.serializer(), this) },
{ json.decodeFromString(ChatSettings.serializer(), this) },
).cached(FullKVCache(), scope = scope)
val chatsChangingMutex = Mutex()
val chatsSendingJobs = mutableMapOf<ChatId, Job>()
// here should be main logic of your bot
bot.buildBehaviourWithLongPolling(scope) {
// in this lambda you will be able to call methods without "bot." prefix
val me = getMe()
// this method will create point to react on each /start command
onCommand("start", requireOnlyCommandInMessage = true) {
// simply reply :)
reply(it, "Hello, I am ${me.firstName}")
suspend fun refreshChatJob(chatId: ChatId, settings: ChatSettings?) {
val settings = settings ?: repo.get(chatId)
chatsChangingMutex.withLock {
chatsSendingJobs[chatId] ?.cancel()
settings ?.let {
chatsSendingJobs[chatId] = settings.scheduler.asFlow().subscribeSafelyWithoutExceptions(scope) {
val result = settings.makeRequest()
when {
result.isEmpty() -> return@subscribeSafelyWithoutExceptions
result.size == 1 -> sendPhoto(
chatId,
FileUrl(result.first().url)
)
settings.gallery -> result.chunked(mediaCountInMediaGroup.last + 1).forEach {
sendVisualMediaGroup(
chatId,
it.map {
TelegramMediaPhoto(FileUrl(it.url))
}
)
}
else -> result.forEach {
sendPhoto(
chatId,
FileUrl(it.url)
)
}
}
}
}
}
}
// That will be called on the end of bot initiation. After that println will be started long polling and bot will
// react on your commands
doForAllWithNextPaging {
repo.keys(it).also {
it.results.forEach {
refreshChatJob(it, null)
}
}
}
repo.onNewValue.subscribeSafelyWithoutExceptions(this) {
refreshChatJob(it.first, it.second)
}
repo.onValueRemoved.subscribeSafelyWithoutExceptions(this) {
refreshChatJob(it, null)
}
onCommand(Regex("(help|start)"), requireOnlyCommandInMessage = true) {
reply(it, EnableArgsParser(it.chat.id, repo, scope).getFormattedHelp().takeIf { it.isNotBlank() } ?: return@onCommand)
}
onCommandWithArgs("enable") { message, strings ->
val parser = EnableArgsParser(message.chat.id, repo, this)
runCatchingSafely {
parser.parse(strings)
}.onFailure { e ->
e.printStackTrace()
if (message.chat is PrivateChat) {
reply(message, parser.getFormattedHelp())
}
}
runCatchingSafely {
if (message.chat is ChannelChat) {
delete(message)
}
}
}
onCommand("disable", requireOnlyCommandInMessage = true) {
runCatchingSafely {
repo.unset(it.chat.id)
}
runCatchingSafely {
delete(it)
}
}
setMyCommands(
listOf(
BotCommand("start", "Will return the help for the enable command"),
BotCommand("help", "Will return the help for the enable command"),
BotCommand("enable", "Will enable images grabbing for current chat or update exists settings"),
BotCommand("disable", "Will disable bot for current chat"),
)
)
println(me)
}.join()
}