diff --git a/common/src/commonMain/kotlin/ChatConfig.kt b/common/src/commonMain/kotlin/ChatConfig.kt index 96f1442..181deb1 100644 --- a/common/src/commonMain/kotlin/ChatConfig.kt +++ b/common/src/commonMain/kotlin/ChatConfig.kt @@ -1,15 +1,27 @@ package dev.inmo.plaguposter.common import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer +import dev.inmo.tgbotapi.types.IdChatIdentifier import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class ChatConfig( @SerialName("targetChat") - val targetChatId: ChatId, + @Serializable(FullChatIdentifierSerializer::class) + val targetChatId: IdChatIdentifier, @SerialName("sourceChat") - val sourceChatId: ChatId, + @Serializable(FullChatIdentifierSerializer::class) + val sourceChatId: IdChatIdentifier, @SerialName("cacheChat") - val cacheChatId: ChatId -) + @Serializable(FullChatIdentifierSerializer::class) + val cacheChatId: IdChatIdentifier +) { + fun check(chatId: IdChatIdentifier) = when (chatId) { + targetChatId, + sourceChatId, + cacheChatId -> true + else -> false + } +} diff --git a/common/src/jvmMain/kotlin/CommonPlugin.kt b/common/src/jvmMain/kotlin/CommonPlugin.kt index e5de8bd..dd8995c 100644 --- a/common/src/jvmMain/kotlin/CommonPlugin.kt +++ b/common/src/jvmMain/kotlin/CommonPlugin.kt @@ -6,10 +6,20 @@ import dev.inmo.kslog.common.logger import dev.inmo.plagubot.Plugin import dev.inmo.tgbotapi.extensions.api.chat.get.getChat import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.serialization.json.JsonObject +import org.jetbrains.exposed.sql.Database import org.koin.core.Koin +import org.koin.core.module.Module object CommonPlugin : Plugin { private val Log = logger + override fun Module.setupDI(database: Database, params: JsonObject) { + single { CoroutineScope(Dispatchers.Default + SupervisorJob()) } + } + override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { val config = koin.get() diff --git a/posts/src/commonMain/kotlin/sending/PostPublisher.kt b/posts/src/commonMain/kotlin/sending/PostPublisher.kt index b603a3d..3073c03 100644 --- a/posts/src/commonMain/kotlin/sending/PostPublisher.kt +++ b/posts/src/commonMain/kotlin/sending/PostPublisher.kt @@ -17,8 +17,8 @@ import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent class PostPublisher( private val bot: TelegramBot, private val postsRepo: PostsRepo, - private val cachingChatId: ChatId, - private val targetChatId: ChatId, + private val cachingChatId: IdChatIdentifier, + private val targetChatId: IdChatIdentifier, private val deleteAfterPosting: Boolean = true ) { suspend fun publish(postId: PostId) { diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index 9706fa9..d48c6b5 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -101,6 +101,7 @@ object Plugin : Plugin { } val post = postsRepo.getById(postId) ?: return false + ratingsRepo.set(postId, Rating(0.0)) for (content in post.content) { runCatchingSafely { val sent = send( @@ -140,7 +141,7 @@ object Plugin : Plugin { } } - postsRepo.deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(this) { postId -> + ratingsRepo.onValueRemoved.subscribeSafelyWithoutExceptions(this) { postId -> detachPoll(postId) } diff --git a/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt b/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt index 0c7f14e..480033b 100644 --- a/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt +++ b/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt @@ -1,6 +1,7 @@ package dev.inmo.plaguposter.ratings.exposed import dev.inmo.micro_utils.pagination.utils.optionallyReverse +import dev.inmo.micro_utils.repos.exposed.initTable import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo import dev.inmo.plaguposter.posts.models.PostId import dev.inmo.plaguposter.ratings.models.Rating @@ -24,6 +25,10 @@ class ExposedRatingsRepo ( override val ResultRow.asObject: Rating get() = get(ratingsColumn).let(::Rating) + init { + initTable() + } + override fun update(k: PostId, v: Rating, it: UpdateBuilder) { it[ratingsColumn] = v.double } diff --git a/runner/build.gradle b/runner/build.gradle index a0622f2..254b167 100644 --- a/runner/build.gradle +++ b/runner/build.gradle @@ -16,6 +16,8 @@ dependencies { api project(":plaguposter.triggers.command") api project(":plaguposter.triggers.selector_with_timer") api project(":plaguposter.triggers.timer") + api project(":plaguposter.triggers.timer.disablers.autoposts") + api project(":plaguposter.triggers.timer.disablers.ratings") api project(":plaguposter.ratings") api project(":plaguposter.ratings.source") api project(":plaguposter.ratings.selector") diff --git a/settings.gradle b/settings.gradle index 8304913..1bb37bc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,8 @@ String[] includes = [ ":triggers:selector_with_timer", ":triggers:selector_with_scheduling", ":triggers:timer", + ":triggers:timer:disablers:ratings", + ":triggers:timer:disablers:autoposts", ":inlines", // ":settings", ":runner" diff --git a/triggers/selector_with_timer/src/commonMain/kotlin/AutopostFilter.kt b/triggers/selector_with_timer/src/commonMain/kotlin/AutopostFilter.kt new file mode 100644 index 0000000..66cd842 --- /dev/null +++ b/triggers/selector_with_timer/src/commonMain/kotlin/AutopostFilter.kt @@ -0,0 +1,8 @@ +package dev.inmo.plaguposter.triggers.selector_with_timer + +import com.soywiz.klock.DateTime +import dev.inmo.plaguposter.posts.models.PostId + +fun interface AutopostFilter { + suspend fun check(postId: PostId, dateTime: DateTime): Boolean +} diff --git a/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt b/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt index 22e5dc3..33f324c 100644 --- a/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt @@ -34,9 +34,12 @@ object Plugin : Plugin { override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { val publisher = koin.get() val selector = koin.get() - koin.get().krontab.asFlow().subscribeSafelyWithoutExceptions(this) { - selector.take(now = it).forEach { postId -> - publisher.publish(postId) + val filters = koin.getAll().distinct() + koin.get().krontab.asFlow().subscribeSafelyWithoutExceptions(this) { dateTime -> + selector.take(now = dateTime).forEach { postId -> + if (filters.all { it.check(postId, dateTime) }) { + publisher.publish(postId) + } } } } diff --git a/triggers/timer/build.gradle b/triggers/timer/build.gradle index 3793d30..aa16791 100644 --- a/triggers/timer/build.gradle +++ b/triggers/timer/build.gradle @@ -11,6 +11,7 @@ kotlin { dependencies { api project(":plaguposter.common") api project(":plaguposter.posts") + api project(":plaguposter.posts.panel") } } } diff --git a/triggers/timer/disablers/autoposts/build.gradle b/triggers/timer/disablers/autoposts/build.gradle new file mode 100644 index 0000000..0bfbf70 --- /dev/null +++ b/triggers/timer/disablers/autoposts/build.gradle @@ -0,0 +1,18 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" +} + +apply from: "$mppProjectWithSerializationPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api project(":plaguposter.common") + api project(":plaguposter.triggers.timer") + api project(":plaguposter.triggers.selector_with_timer") + } + } + } +} diff --git a/triggers/timer/disablers/autoposts/src/commonMain/kotlin/PackageInfo.kt b/triggers/timer/disablers/autoposts/src/commonMain/kotlin/PackageInfo.kt new file mode 100644 index 0000000..1df25ed --- /dev/null +++ b/triggers/timer/disablers/autoposts/src/commonMain/kotlin/PackageInfo.kt @@ -0,0 +1 @@ +package dev.inmo.plaguposter.triggers.timer.disablers.autoposts diff --git a/triggers/timer/disablers/autoposts/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/disablers/autoposts/src/jvmMain/kotlin/Plugin.kt new file mode 100644 index 0000000..d301480 --- /dev/null +++ b/triggers/timer/disablers/autoposts/src/jvmMain/kotlin/Plugin.kt @@ -0,0 +1,27 @@ +package dev.inmo.plaguposter.triggers.timer.disablers.autoposts + +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.koin.singleWithRandomQualifier +import dev.inmo.micro_utils.koin.singleWithRandomQualifierAndBinds +import dev.inmo.micro_utils.pagination.FirstPagePagination +import dev.inmo.micro_utils.repos.unset +import dev.inmo.plagubot.Plugin +import dev.inmo.plaguposter.ratings.repo.RatingsRepo +import dev.inmo.plaguposter.triggers.selector_with_timer.AutopostFilter +import dev.inmo.plaguposter.triggers.timer.TimersRepo +import kotlinx.coroutines.CoroutineScope +import kotlinx.serialization.json.* +import org.jetbrains.exposed.sql.Database +import org.koin.core.module.Module + +object Plugin : Plugin { + override fun Module.setupDI(database: Database, params: JsonObject) { + singleWithRandomQualifier { + val timersRepo = get() + AutopostFilter { _, dateTime -> + val result = timersRepo.keys(dateTime, FirstPagePagination(1)) + result.results.isEmpty() + } + } + } +} diff --git a/triggers/timer/disablers/autoposts/src/main/AndroidManifest.xml b/triggers/timer/disablers/autoposts/src/main/AndroidManifest.xml new file mode 100644 index 0000000..602c1bc --- /dev/null +++ b/triggers/timer/disablers/autoposts/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/triggers/timer/disablers/ratings/build.gradle b/triggers/timer/disablers/ratings/build.gradle new file mode 100644 index 0000000..429e53f --- /dev/null +++ b/triggers/timer/disablers/ratings/build.gradle @@ -0,0 +1,18 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" +} + +apply from: "$mppProjectWithSerializationPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api project(":plaguposter.common") + api project(":plaguposter.triggers.timer") + api project(":plaguposter.ratings") + } + } + } +} diff --git a/triggers/timer/disablers/ratings/src/commonMain/kotlin/PackageInfo.kt b/triggers/timer/disablers/ratings/src/commonMain/kotlin/PackageInfo.kt new file mode 100644 index 0000000..71d2ee0 --- /dev/null +++ b/triggers/timer/disablers/ratings/src/commonMain/kotlin/PackageInfo.kt @@ -0,0 +1 @@ +package dev.inmo.plaguposter.triggers.timer.disablers.ratings diff --git a/triggers/timer/disablers/ratings/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/disablers/ratings/src/jvmMain/kotlin/Plugin.kt new file mode 100644 index 0000000..af960ef --- /dev/null +++ b/triggers/timer/disablers/ratings/src/jvmMain/kotlin/Plugin.kt @@ -0,0 +1,26 @@ +package dev.inmo.plaguposter.triggers.timer.disablers.ratings + +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.koin.singleWithRandomQualifier +import dev.inmo.micro_utils.repos.unset +import dev.inmo.plagubot.Plugin +import dev.inmo.plaguposter.ratings.repo.RatingsRepo +import dev.inmo.plaguposter.triggers.timer.TimersRepo +import kotlinx.coroutines.CoroutineScope +import kotlinx.serialization.json.* +import org.jetbrains.exposed.sql.Database +import org.koin.core.module.Module + +object Plugin : Plugin { + override fun Module.setupDI(database: Database, params: JsonObject) { + singleWithRandomQualifier(createdAtStart = true) { + val timersRepo = get() + val ratingsRepo = get() + val scope = get() + + timersRepo.onNewValue.subscribeSafelyWithoutExceptions(scope) { + ratingsRepo.unset(it.first) + } + } + } +} diff --git a/triggers/timer/disablers/ratings/src/main/AndroidManifest.xml b/triggers/timer/disablers/ratings/src/main/AndroidManifest.xml new file mode 100644 index 0000000..caad574 --- /dev/null +++ b/triggers/timer/disablers/ratings/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index 56c2fd8..f1db4f4 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -1,54 +1,87 @@ package dev.inmo.plaguposter.triggers.timer +import com.soywiz.klock.DateFormat import com.soywiz.klock.DateTime import com.soywiz.klock.DateTimeTz import com.soywiz.klock.Month import com.soywiz.klock.Year import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.repos.unset import dev.inmo.plaguposter.common.SuccessfulSymbol -import dev.inmo.plaguposter.posts.models.Post +import dev.inmo.plaguposter.common.UnsuccessfulSymbol import dev.inmo.plaguposter.posts.models.PostId import dev.inmo.tgbotapi.extensions.api.answers.answer +import dev.inmo.tgbotapi.extensions.api.delete import dev.inmo.tgbotapi.extensions.api.edit.edit import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery 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.inlineKeyboard +import dev.inmo.tgbotapi.extensions.utils.withContentOrNull import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.utils.bold +import dev.inmo.tgbotapi.utils.buildEntities import dev.inmo.tgbotapi.utils.row object ButtonsBuilder { + private const val changeTimeData = "timer_time_hint" + private const val changeDateData = "timer_date_hint" private const val changeHoursDataPrefix = "timer_h" private const val changeMinutesDataPrefix = "timer_m" private const val changeDayDataPrefix = "timer_d" private const val changeMonthDataPrefix = "timer_M" private const val changeYearDataPrefix = "timer_y" private const val changeDateDataPrefix = "timer_s" + private const val cancelDateData = "timer_c" + private const val deleteDateDataPrefix = "timer_r" + val datePrintFormat = DateFormat("hh:mm, dd.MM.yyyy, zzz") fun buildTimerButtons( postId: PostId, - dateTime: DateTimeTz - ) = flatInlineKeyboard { + dateTime: DateTimeTz, + exists: Boolean + ) = inlineKeyboard { val unixMillis = dateTime.utc.unixMillisLong - dataButton(dateTime.hours.toString(), "$changeHoursDataPrefix $postId $unixMillis") - dataButton(":${dateTime.minutes}", "$changeMinutesDataPrefix $postId $unixMillis") + row { + dataButton("Time:", changeTimeData) + dataButton(dateTime.hours.toString(), "$changeHoursDataPrefix $postId $unixMillis") + dataButton(dateTime.minutes.toString(), "$changeMinutesDataPrefix $postId $unixMillis") + } + row { + dataButton("Date:", changeDateData) + dataButton(dateTime.dayOfMonth.toString(), "$changeDayDataPrefix $postId $unixMillis") + dataButton(dateTime.month1.toString(), "$changeMonthDataPrefix $postId $unixMillis") + dataButton(dateTime.yearInt.toString(), "$changeYearDataPrefix $postId $unixMillis") + } - dataButton(dateTime.dayOfMonth.toString(), "$changeDayDataPrefix $postId $unixMillis") - dataButton(".${dateTime.month1}", "$changeMonthDataPrefix $postId $unixMillis") - dataButton(".${dateTime.yearInt}", "$changeYearDataPrefix $postId $unixMillis") + row { + if (exists) { + dataButton("\uD83D\uDDD1", "$deleteDateDataPrefix $postId") + } + dataButton(UnsuccessfulSymbol, cancelDateData) + dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis") + } + } - dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis") + fun buildTimerTextSources( + currentDateTime: DateTime, + previousTime: DateTime? + ) = buildEntities { + previousTime ?.let { + + "Previous timer time: " + bold(it.local.toString(datePrintFormat)) + "\n" + } + +"Currently editing time: " + bold(currentDateTime.local.toString(datePrintFormat)) } suspend fun BehaviourContext.includeKeyboardHandling( + timersRepo: TimersRepo, onSavePublishingTime: suspend (PostId, DateTime) -> Boolean ) { fun buildKeyboard( prefix: String, postId: PostId, values: Iterable, - min: DateTime = DateTime.now(), + min: DateTime = nearestAvailableTimerTime(), dateConverter: (Int) -> DateTimeTz ): InlineKeyboardMarkup { return inlineKeyboard { @@ -90,13 +123,18 @@ object ButtonsBuilder { val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery val currentDateTime = DateTime(currentMillis) + val postId = PostId(rawPostId) + val previousTime = timersRepo.get(postId) edit( - it.message, - buildTimerButtons( - PostId(rawPostId), - currentDateTime.local + it.message.withContentOrNull() ?: return@onMessageDataCallbackQuery, + replyMarkup = buildTimerButtons( + postId, + currentDateTime.local, + timersRepo.contains(postId) ) - ) + ) { + +buildTimerTextSources(currentDateTime, previousTime) + } } } @@ -105,7 +143,7 @@ object ButtonsBuilder { buildStandardDataCallbackQuery( changeHoursDataPrefix, { - val now = DateTime.now().local + val now = nearestAvailableTimerTime().local if (now.dateEq(it)) { now.hours .. 23 @@ -123,7 +161,7 @@ object ButtonsBuilder { buildStandardDataCallbackQuery( changeMinutesDataPrefix, { - val now = DateTime.now().local + val now = nearestAvailableTimerTime().local if (now.dateEq(it) && now.hours >= it.hours) { now.minutes until 60 @@ -141,7 +179,7 @@ object ButtonsBuilder { buildStandardDataCallbackQuery( changeDayDataPrefix, { - val now = DateTime.now().local + val now = nearestAvailableTimerTime().local if (now.yearInt == it.yearInt && now.month0 == it.month0) { now.dayOfMonth .. it.month.days(it.year) @@ -159,7 +197,7 @@ object ButtonsBuilder { buildStandardDataCallbackQuery( changeMonthDataPrefix, { - val now = DateTime.now().local + val now = nearestAvailableTimerTime().local if (now.year == it.year) { now.month1 .. 12 @@ -177,7 +215,8 @@ object ButtonsBuilder { buildStandardDataCallbackQuery( changeYearDataPrefix, { - (it.year.year .. (it.year.year + 5)) + val now = nearestAvailableTimerTime().local + (now.year.year .. (now.year.year + 5)) } ) { newValue, oldDateTime -> DateTimeTz.local( @@ -186,6 +225,14 @@ object ButtonsBuilder { ) } + onMessageDataCallbackQuery(changeTimeData) { + answer(it, "Use the buttons to the right to set post publishing time (hh:mm)", showAlert = true) + } + + onMessageDataCallbackQuery(changeDateData) { + answer(it, "Use the buttons to the right to set post publishing date (dd.MM.yyyy)", showAlert = true) + } + onMessageDataCallbackQuery(Regex("$changeDateDataPrefix .*")) { val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ") val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery @@ -200,6 +247,29 @@ object ButtonsBuilder { it, if (success) "Successfully set timer" else "Unable to set timer" ) + + it.message.delete(this) + } + + onMessageDataCallbackQuery(Regex("$deleteDateDataPrefix .*")) { + val (_, rawPostId) = it.data.split(" ") + val postId = PostId(rawPostId) + + val success = runCatchingSafely { + timersRepo.unset(postId) + true + }.getOrElse { false } + + answer( + it, + if (success) "Successfully unset timer" else "Unable to unset timer" + ) + + it.message.delete(this) + } + + onMessageDataCallbackQuery(cancelDateData) { + delete(it.message) } } } diff --git a/triggers/timer/src/commonMain/kotlin/NearestAvailablePublishingTime.kt b/triggers/timer/src/commonMain/kotlin/NearestAvailablePublishingTime.kt new file mode 100644 index 0000000..55db364 --- /dev/null +++ b/triggers/timer/src/commonMain/kotlin/NearestAvailablePublishingTime.kt @@ -0,0 +1,9 @@ +package dev.inmo.plaguposter.triggers.timer + +import com.soywiz.klock.DateTime +import com.soywiz.klock.minutes + +fun nearestAvailableTimerTime() = (DateTime.now() + 1.minutes).copyDayOfMonth( + milliseconds = 0, + seconds = 0 +) diff --git a/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt b/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt new file mode 100644 index 0000000..729d3df --- /dev/null +++ b/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt @@ -0,0 +1,28 @@ +package dev.inmo.plaguposter.triggers.timer + +import dev.inmo.plaguposter.common.SuccessfulSymbol +import dev.inmo.plaguposter.common.UnsuccessfulSymbol +import dev.inmo.plaguposter.posts.models.RegisteredPost +import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton + +class TimerPanelButton( + private val timersRepo: TimersRepo +) : PanelButtonBuilder { + override val weight: Int + get() = 0 + + override suspend fun buildButton(post: RegisteredPost): InlineKeyboardButton? { + val publishingTime = timersRepo.get(post.id) + + return CallbackDataInlineKeyboardButton( + "⏰ ${ if (publishingTime == null) UnsuccessfulSymbol else SuccessfulSymbol }", + "$timerSetPrefix ${post.id}" + ) + } + + companion object { + const val timerSetPrefix = "timer_set_init" + } +} diff --git a/triggers/timer/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/src/jvmMain/kotlin/Plugin.kt index d4f719b..088c278 100644 --- a/triggers/timer/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/timer/src/jvmMain/kotlin/Plugin.kt @@ -2,14 +2,20 @@ package dev.inmo.plaguposter.triggers.timer import com.soywiz.klock.DateTime import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.koin.singleWithRandomQualifierAndBinds import dev.inmo.micro_utils.repos.set import dev.inmo.plagubot.Plugin +import dev.inmo.plaguposter.common.ChatConfig +import dev.inmo.plaguposter.posts.models.PostId import dev.inmo.plaguposter.posts.repo.ReadPostsRepo import dev.inmo.plaguposter.triggers.timer.repo.ExposedTimersRepo +import dev.inmo.tgbotapi.extensions.api.answers.answer import dev.inmo.tgbotapi.extensions.api.edit.edit +import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery import kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database import org.koin.core.Koin @@ -20,39 +26,41 @@ object Plugin : Plugin { override fun Module.setupDI(database: Database, params: JsonObject) { single { ExposedTimersRepo(get(), get(), get()) } binds arrayOf(TimersRepo::class) single(createdAtStart = true) { TimersHandler(get(), get(), get()) } + singleWithRandomQualifierAndBinds { TimerPanelButton(get()) } } override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { - val postsRepo = koin.get() val timersRepo = koin.get() + val chatsConfig = koin.get() with(ButtonsBuilder) { - includeKeyboardHandling { postId, dateTime -> + includeKeyboardHandling(timersRepo) { postId, dateTime -> timersRepo.set(postId, dateTime) true } } - onCommand("test") { - val reply = it.replyTo ?: return@onCommand - val postId = postsRepo.getIdByChatAndMessage( - reply.chat.id, - reply.messageId - ) ?: return@onCommand + onMessageDataCallbackQuery( + Regex("${TimerPanelButton.timerSetPrefix} [^\\s]+"), + initialFilter = { + chatsConfig.check(it.message.chat.id) + } + ) { + val (_, postIdRaw) = it.data.split(" ") + val postId = PostId(postIdRaw) + val now = nearestAvailableTimerTime() + val exists = timersRepo.get(postId) + val textSources = ButtonsBuilder.buildTimerTextSources(now, exists) val buttons = ButtonsBuilder.buildTimerButtons( postId, - DateTime.nowLocal() + now.local, + exists != null ) - runCatchingSafely { - edit( - it, - buttons - ) - }.onFailure { _ -> - send( - it.chat, - "Buttons", - replyMarkup = buttons - ) - } + reply( + it.message, + textSources, + replyMarkup = buttons + ) + + answer(it) } } }