From 8c42f2e8798855e765a38721aa1c991a13134f8d Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 13 Dec 2022 11:27:57 +0600 Subject: [PATCH 01/14] update dependencies --- gradle.properties | 3 +-- gradle/libs.versions.toml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 114a8d3..1aafafe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,5 +10,4 @@ android.enableJetifier=true # Project data group=dev.inmo -version=0.0.7 -android_code_version=7 +version=0.0.8 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ed6924d..cef955b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,9 +3,9 @@ kotlin = "1.7.22" kotlin-serialization = "1.4.1" -plagubot = "3.2.0" +plagubot = "3.2.1" tgbotapi = "4.2.1" -microutils = "0.16.0" +microutils = "0.16.1" kslog = "0.5.4" krontab = "0.8.4" tgbotapi-libraries = "0.6.5" From 65dfe8abd03bbf4c95dea0e8e7057d19c7aaf5ab Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 13 Dec 2022 12:32:18 +0600 Subject: [PATCH 02/14] start adding of timer --- posts/src/commonMain/kotlin/models/PostId.kt | 4 +- settings.gradle | 1 + triggers/timer/build.gradle | 17 ++ .../src/commonMain/kotlin/ButtonsBuilder.kt | 145 ++++++++++++++++++ .../src/commonMain/kotlin/PackageInfo.kt | 1 + triggers/timer/src/jvmMain/kotlin/Plugin.kt | 11 ++ triggers/timer/src/main/AndroidManifest.xml | 1 + 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 triggers/timer/build.gradle create mode 100644 triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt create mode 100644 triggers/timer/src/commonMain/kotlin/PackageInfo.kt create mode 100644 triggers/timer/src/jvmMain/kotlin/Plugin.kt create mode 100644 triggers/timer/src/main/AndroidManifest.xml diff --git a/posts/src/commonMain/kotlin/models/PostId.kt b/posts/src/commonMain/kotlin/models/PostId.kt index 806d412..e3ff56d 100644 --- a/posts/src/commonMain/kotlin/models/PostId.kt +++ b/posts/src/commonMain/kotlin/models/PostId.kt @@ -7,4 +7,6 @@ import kotlin.jvm.JvmInline @JvmInline value class PostId( val string: String -) +) { + override fun toString(): String = string +} diff --git a/settings.gradle b/settings.gradle index 4974edb..8304913 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ String[] includes = [ ":triggers:command", ":triggers:selector_with_timer", ":triggers:selector_with_scheduling", + ":triggers:timer", ":inlines", // ":settings", ":runner" diff --git a/triggers/timer/build.gradle b/triggers/timer/build.gradle new file mode 100644 index 0000000..3793d30 --- /dev/null +++ b/triggers/timer/build.gradle @@ -0,0 +1,17 @@ +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.posts") + } + } + } +} diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt new file mode 100644 index 0000000..db4c3de --- /dev/null +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -0,0 +1,145 @@ +package dev.inmo.plaguposter.triggers.timer + +import com.soywiz.klock.DateTime +import com.soywiz.klock.DateTimeTz +import com.soywiz.klock.Month +import dev.inmo.plaguposter.common.SuccessfulSymbol +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.tgbotapi.extensions.api.answers.answer +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.commonMessageOrNull +import dev.inmo.tgbotapi.extensions.utils.extensions.raw.reply_markup +import dev.inmo.tgbotapi.extensions.utils.ifCallbackDataInlineKeyboardButton +import dev.inmo.tgbotapi.extensions.utils.ifCommonMessage +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.withContent +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.types.queries.callback.MessageDataCallbackQuery +import dev.inmo.tgbotapi.utils.row + +object ButtonsBuilder { + private const val changeHoursDataPrefix = "timer_hours" + private const val changeMinutesDataPrefix = "timer_minutes" + private const val changeDayDataPrefix = "timer_day" + private const val changeMonthDataPrefix = "timer_month" + private const val changeYearDataPrefix = "timer_year" + private const val changeDateDataPrefix = "timer_set" + + private fun buildTimerButtons( + postId: PostId, + dateTime: DateTime + ) = flatInlineKeyboard { + val unixMillis = dateTime.unixMillisLong + val local = dateTime.local + dataButton(local.hours.toString(), "$changeHoursDataPrefix $postId $unixMillis") + dataButton(":${local.minutes}", "$changeMinutesDataPrefix $postId $unixMillis") + + dataButton(local.dayOfMonth.toString(), "$changeDayDataPrefix $postId $unixMillis") + dataButton(".${local.month1}", "$changeMonthDataPrefix $postId $unixMillis") + dataButton(".${local.yearInt}", "$changeYearDataPrefix $postId $unixMillis") + + dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis") + } + + suspend fun BehaviourContext.includeKeyboardHandling() { + fun buildKeyboard( + prefix: String, + postId: PostId, + values: Iterable, + dateConverter: (Int) -> DateTime + ): InlineKeyboardMarkup { + return inlineKeyboard { + values.chunked(5).forEach { + row { + it.forEach { + dataButton(it.toString(), "$prefix $postId ${dateConverter(it).unixMillisLong}") + } + } + } + } + } + + suspend fun buildStandardDataCallbackQuery( + prefix: String, + possibleValues: (DateTime) -> Iterable, + dateTimeConverter: (Int, DateTime) -> DateTime + ) { + val setPrefix = "${prefix}_set" + onMessageDataCallbackQuery(Regex("$prefix .+")) { + val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ") + val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery + val currentDateTime = DateTime(currentMillis) + + edit ( + it.message, + replyMarkup = buildKeyboard( + setPrefix, + PostId(rawPostId), + possibleValues(DateTime(currentMillis)) + ) { + dateTimeConverter(it, currentDateTime) + } + ) + } + + onMessageDataCallbackQuery(Regex("$setPrefix .+")) { + val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ") + + val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery + val currentDateTime = DateTime(currentMillis) + edit( + it.message, + buildTimerButtons( + PostId(rawPostId), + currentDateTime + ) + ) + } + } + + buildStandardDataCallbackQuery( + changeHoursDataPrefix, + (0 until 24).toList().let { { _ -> it } } // TODO::Add filter of hours which are in the past + ) { newValue, oldDateTime -> + oldDateTime.copyDayOfMonth(hours = newValue) + } + + buildStandardDataCallbackQuery( + changeMinutesDataPrefix, + (0 until 60).toList().let { { _ -> it } } // TODO::Add filter of hours which are in the past + ) { newValue, oldDateTime -> + oldDateTime.copyDayOfMonth(minutes = newValue) + } + + buildStandardDataCallbackQuery( + changeDayDataPrefix, + { + val days = it.month.days(it.year) + + 1 .. days + } // TODO::Add filter of hours which are in the past + ) { newValue, oldDateTime -> + oldDateTime.copyDayOfMonth(dayOfMonth = newValue) + } + + buildStandardDataCallbackQuery( + changeMonthDataPrefix, + (1 .. 12).toList().let { { _ -> it } } // TODO::Add filter of hours which are in the past + ) { newValue, oldDateTime -> + oldDateTime.copyDayOfMonth(month = Month(newValue)) + } + + buildStandardDataCallbackQuery( + changeYearDataPrefix, + { + (it.year.year .. (it.year.year + 5)) + } + ) { newValue, oldDateTime -> + oldDateTime.copyDayOfMonth(month = Month(newValue)) + } + } +} diff --git a/triggers/timer/src/commonMain/kotlin/PackageInfo.kt b/triggers/timer/src/commonMain/kotlin/PackageInfo.kt new file mode 100644 index 0000000..e9843c7 --- /dev/null +++ b/triggers/timer/src/commonMain/kotlin/PackageInfo.kt @@ -0,0 +1 @@ +package dev.inmo.plaguposter.triggers.timer diff --git a/triggers/timer/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/src/jvmMain/kotlin/Plugin.kt new file mode 100644 index 0000000..dbf4100 --- /dev/null +++ b/triggers/timer/src/jvmMain/kotlin/Plugin.kt @@ -0,0 +1,11 @@ +package dev.inmo.plaguposter.triggers.timer + +import dev.inmo.plagubot.Plugin +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) { + } +} diff --git a/triggers/timer/src/main/AndroidManifest.xml b/triggers/timer/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ef864ed --- /dev/null +++ b/triggers/timer/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + From 34e253a12e47bbe6b8d4158a15e5864b567d8840 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 13 Dec 2022 12:39:32 +0600 Subject: [PATCH 03/14] add checking of current date --- .../src/commonMain/kotlin/ButtonsBuilder.kt | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index db4c3de..67181a7 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -101,16 +101,36 @@ object ButtonsBuilder { } } + fun DateTimeTz.dateEq(other: DateTimeTz) = yearInt == other.yearInt && month0 == other.month0 && dayOfMonth == other.dayOfMonth + buildStandardDataCallbackQuery( changeHoursDataPrefix, - (0 until 24).toList().let { { _ -> it } } // TODO::Add filter of hours which are in the past + { + val now = DateTime.now().local + val local = it.local + + if (now.dateEq(local)) { + now.hours .. 23 + } else { + 0 .. 23 + } + } ) { newValue, oldDateTime -> oldDateTime.copyDayOfMonth(hours = newValue) } buildStandardDataCallbackQuery( changeMinutesDataPrefix, - (0 until 60).toList().let { { _ -> it } } // TODO::Add filter of hours which are in the past + { + val now = DateTime.now().local + val local = it.local + + if (now.dateEq(local)) { + now.minutes .. 60 + } else { + 0 .. 60 + } + } ) { newValue, oldDateTime -> oldDateTime.copyDayOfMonth(minutes = newValue) } @@ -118,17 +138,31 @@ object ButtonsBuilder { buildStandardDataCallbackQuery( changeDayDataPrefix, { - val days = it.month.days(it.year) + val now = DateTime.now().local + val local = it.local - 1 .. days - } // TODO::Add filter of hours which are in the past + if (now.dateEq(local)) { + now.dayOfMonth .. it.month.days(it.year) + } else { + 1 .. it.month.days(it.year) + } + } ) { newValue, oldDateTime -> oldDateTime.copyDayOfMonth(dayOfMonth = newValue) } buildStandardDataCallbackQuery( changeMonthDataPrefix, - (1 .. 12).toList().let { { _ -> it } } // TODO::Add filter of hours which are in the past + { + val now = DateTime.now().local + val local = it.local + + if (now.year == local.year) { + now.month1 .. 12 + } else { + 1 .. 12 + } + } ) { newValue, oldDateTime -> oldDateTime.copyDayOfMonth(month = Month(newValue)) } From 74f3503413dc8ee0f56c190439fff20bdc08069e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 13 Dec 2022 12:41:30 +0600 Subject: [PATCH 04/14] add fix todo --- .../timer/src/commonMain/kotlin/ButtonsBuilder.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index 67181a7..2b18123 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -3,6 +3,7 @@ package dev.inmo.plaguposter.triggers.timer import com.soywiz.klock.DateTime import com.soywiz.klock.DateTimeTz import com.soywiz.klock.Month +import com.soywiz.klock.Year import dev.inmo.plaguposter.common.SuccessfulSymbol import dev.inmo.plaguposter.posts.models.PostId import dev.inmo.tgbotapi.extensions.api.answers.answer @@ -116,7 +117,7 @@ object ButtonsBuilder { } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(hours = newValue) + oldDateTime.copyDayOfMonth(hours = newValue) // TODO::Fix issue in case of local and utc diff } buildStandardDataCallbackQuery( @@ -132,7 +133,7 @@ object ButtonsBuilder { } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(minutes = newValue) + oldDateTime.copyDayOfMonth(minutes = newValue) // TODO::Fix issue in case of local and utc diff } buildStandardDataCallbackQuery( @@ -148,7 +149,7 @@ object ButtonsBuilder { } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(dayOfMonth = newValue) + oldDateTime.copyDayOfMonth(dayOfMonth = newValue) // TODO::Fix issue in case of local and utc diff } buildStandardDataCallbackQuery( @@ -164,7 +165,7 @@ object ButtonsBuilder { } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(month = Month(newValue)) + oldDateTime.copyDayOfMonth(month = Month(newValue)) // TODO::Fix issue in case of local and utc diff } buildStandardDataCallbackQuery( @@ -173,7 +174,7 @@ object ButtonsBuilder { (it.year.year .. (it.year.year + 5)) } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(month = Month(newValue)) + oldDateTime.copyDayOfMonth(year = Year(newValue)) // TODO::Fix issue in case of local and utc diff } } } From 00803fa9331895cb756227a8319d2f2e096e0a62 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 13 Dec 2022 13:16:55 +0600 Subject: [PATCH 05/14] fixes --- runner/build.gradle | 1 + .../src/commonMain/kotlin/ButtonsBuilder.kt | 94 ++++++++++--------- triggers/timer/src/jvmMain/kotlin/Plugin.kt | 38 ++++++++ 3 files changed, 88 insertions(+), 45 deletions(-) diff --git a/runner/build.gradle b/runner/build.gradle index d7cf67f..a0622f2 100644 --- a/runner/build.gradle +++ b/runner/build.gradle @@ -15,6 +15,7 @@ dependencies { api project(":plaguposter.posts_registrar") api project(":plaguposter.triggers.command") api project(":plaguposter.triggers.selector_with_timer") + api project(":plaguposter.triggers.timer") api project(":plaguposter.ratings") api project(":plaguposter.ratings.source") api project(":plaguposter.ratings.selector") diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index 2b18123..d78d569 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -6,42 +6,34 @@ import com.soywiz.klock.Month import com.soywiz.klock.Year import dev.inmo.plaguposter.common.SuccessfulSymbol import dev.inmo.plaguposter.posts.models.PostId -import dev.inmo.tgbotapi.extensions.api.answers.answer 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.commonMessageOrNull -import dev.inmo.tgbotapi.extensions.utils.extensions.raw.reply_markup -import dev.inmo.tgbotapi.extensions.utils.ifCallbackDataInlineKeyboardButton -import dev.inmo.tgbotapi.extensions.utils.ifCommonMessage 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.withContent import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup -import dev.inmo.tgbotapi.types.queries.callback.MessageDataCallbackQuery import dev.inmo.tgbotapi.utils.row object ButtonsBuilder { - private const val changeHoursDataPrefix = "timer_hours" - private const val changeMinutesDataPrefix = "timer_minutes" - private const val changeDayDataPrefix = "timer_day" - private const val changeMonthDataPrefix = "timer_month" - private const val changeYearDataPrefix = "timer_year" - private const val changeDateDataPrefix = "timer_set" + 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 fun buildTimerButtons( + fun buildTimerButtons( postId: PostId, - dateTime: DateTime + dateTime: DateTimeTz ) = flatInlineKeyboard { - val unixMillis = dateTime.unixMillisLong - val local = dateTime.local - dataButton(local.hours.toString(), "$changeHoursDataPrefix $postId $unixMillis") - dataButton(":${local.minutes}", "$changeMinutesDataPrefix $postId $unixMillis") + val unixMillis = dateTime.utc.unixMillisLong + dataButton(dateTime.hours.toString(), "$changeHoursDataPrefix $postId $unixMillis") + dataButton(":${dateTime.minutes}", "$changeMinutesDataPrefix $postId $unixMillis") - dataButton(local.dayOfMonth.toString(), "$changeDayDataPrefix $postId $unixMillis") - dataButton(".${local.month1}", "$changeMonthDataPrefix $postId $unixMillis") - dataButton(".${local.yearInt}", "$changeYearDataPrefix $postId $unixMillis") + dataButton(dateTime.dayOfMonth.toString(), "$changeDayDataPrefix $postId $unixMillis") + dataButton(".${dateTime.month1}", "$changeMonthDataPrefix $postId $unixMillis") + dataButton(".${dateTime.yearInt}", "$changeYearDataPrefix $postId $unixMillis") dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis") } @@ -51,13 +43,14 @@ object ButtonsBuilder { prefix: String, postId: PostId, values: Iterable, - dateConverter: (Int) -> DateTime + min: DateTime = DateTime.now(), + dateConverter: (Int) -> DateTimeTz ): InlineKeyboardMarkup { return inlineKeyboard { values.chunked(5).forEach { row { it.forEach { - dataButton(it.toString(), "$prefix $postId ${dateConverter(it).unixMillisLong}") + dataButton(it.toString(), "$prefix $postId ${dateConverter(it).utc.unixMillisLong.coerceAtLeast(min.unixMillisLong)}") } } } @@ -66,21 +59,21 @@ object ButtonsBuilder { suspend fun buildStandardDataCallbackQuery( prefix: String, - possibleValues: (DateTime) -> Iterable, - dateTimeConverter: (Int, DateTime) -> DateTime + possibleValues: (DateTimeTz) -> Iterable, + dateTimeConverter: (Int, DateTimeTz) -> DateTimeTz ) { - val setPrefix = "${prefix}_set" + val setPrefix = "${prefix}s" onMessageDataCallbackQuery(Regex("$prefix .+")) { val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ") val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery - val currentDateTime = DateTime(currentMillis) + val currentDateTime = DateTime(currentMillis).local edit ( it.message, replyMarkup = buildKeyboard( setPrefix, PostId(rawPostId), - possibleValues(DateTime(currentMillis)) + possibleValues(currentDateTime) ) { dateTimeConverter(it, currentDateTime) } @@ -96,7 +89,7 @@ object ButtonsBuilder { it.message, buildTimerButtons( PostId(rawPostId), - currentDateTime + currentDateTime.local ) ) } @@ -108,64 +101,72 @@ object ButtonsBuilder { changeHoursDataPrefix, { val now = DateTime.now().local - val local = it.local - if (now.dateEq(local)) { + if (now.dateEq(it)) { now.hours .. 23 } else { 0 .. 23 } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(hours = newValue) // TODO::Fix issue in case of local and utc diff + DateTimeTz.local( + oldDateTime.local.copyDayOfMonth(hours = newValue), + oldDateTime.offset + ) } buildStandardDataCallbackQuery( changeMinutesDataPrefix, { val now = DateTime.now().local - val local = it.local - if (now.dateEq(local)) { - now.minutes .. 60 + if (now.dateEq(it) && now.hours >= it.hours) { + now.minutes until 60 } else { - 0 .. 60 + 0 until 60 } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(minutes = newValue) // TODO::Fix issue in case of local and utc diff + DateTimeTz.local( + oldDateTime.local.copyDayOfMonth(minutes = newValue), + oldDateTime.offset + ) } buildStandardDataCallbackQuery( changeDayDataPrefix, { val now = DateTime.now().local - val local = it.local - if (now.dateEq(local)) { + if (now.yearInt == it.yearInt && now.month0 == it.month0) { now.dayOfMonth .. it.month.days(it.year) } else { 1 .. it.month.days(it.year) } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(dayOfMonth = newValue) // TODO::Fix issue in case of local and utc diff + DateTimeTz.local( + oldDateTime.local.copyDayOfMonth(dayOfMonth = newValue), + oldDateTime.offset + ) } buildStandardDataCallbackQuery( changeMonthDataPrefix, { val now = DateTime.now().local - val local = it.local - if (now.year == local.year) { + if (now.year == it.year) { now.month1 .. 12 } else { 1 .. 12 } } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(month = Month(newValue)) // TODO::Fix issue in case of local and utc diff + DateTimeTz.local( + oldDateTime.local.copyDayOfMonth(month = Month(newValue)), + oldDateTime.offset + ) } buildStandardDataCallbackQuery( @@ -174,7 +175,10 @@ object ButtonsBuilder { (it.year.year .. (it.year.year + 5)) } ) { newValue, oldDateTime -> - oldDateTime.copyDayOfMonth(year = Year(newValue)) // TODO::Fix issue in case of local and utc diff + DateTimeTz.local( + oldDateTime.local.copyDayOfMonth(year = Year(newValue)), + oldDateTime.offset + ) } } } diff --git a/triggers/timer/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/src/jvmMain/kotlin/Plugin.kt index dbf4100..f0ebf38 100644 --- a/triggers/timer/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/timer/src/jvmMain/kotlin/Plugin.kt @@ -1,11 +1,49 @@ package dev.inmo.plaguposter.triggers.timer +import com.soywiz.klock.DateTime +import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.plagubot.Plugin +import dev.inmo.plaguposter.posts.repo.ReadPostsRepo +import dev.inmo.tgbotapi.extensions.api.edit.edit +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 kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database +import org.koin.core.Koin import org.koin.core.module.Module object Plugin : Plugin { override fun Module.setupDI(database: Database, params: JsonObject) { } + + override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { + val postsRepo = koin.get() + with(ButtonsBuilder) { + includeKeyboardHandling() + } + onCommand("test") { + val reply = it.replyTo ?: return@onCommand + val postId = postsRepo.getIdByChatAndMessage( + reply.chat.id, + reply.messageId + ) ?: return@onCommand + val buttons = ButtonsBuilder.buildTimerButtons( + postId, + DateTime.nowLocal() + ) + runCatchingSafely { + edit( + it, + buttons + ) + }.onFailure { _ -> + send( + it.chat, + "Buttons", + replyMarkup = buttons + ) + } + } + } } From 9403b133f954d05fefa2c4e5d9d132f7dbcc8fea Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 13 Dec 2022 14:00:13 +0600 Subject: [PATCH 06/14] Update ButtonsBuilder.kt --- triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index d78d569..f34b0f5 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -47,7 +47,7 @@ object ButtonsBuilder { dateConverter: (Int) -> DateTimeTz ): InlineKeyboardMarkup { return inlineKeyboard { - values.chunked(5).forEach { + values.chunked(6).forEach { row { it.forEach { dataButton(it.toString(), "$prefix $postId ${dateConverter(it).utc.unixMillisLong.coerceAtLeast(min.unixMillisLong)}") From c632a2ba14d0504ca1e9c2f596ca601691f2ca0b Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 09:43:12 +0600 Subject: [PATCH 07/14] add timers repo and timers handler --- .../src/commonMain/kotlin/ButtonsBuilder.kt | 23 ++++++- .../src/commonMain/kotlin/TimersHandler.kt | 57 +++++++++++++++++ .../timer/src/commonMain/kotlin/TimersRepo.kt | 9 +++ triggers/timer/src/jvmMain/kotlin/Plugin.kt | 11 +++- .../jvmMain/kotlin/repo/ExposedTimersRepo.kt | 62 +++++++++++++++++++ 5 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 triggers/timer/src/commonMain/kotlin/TimersHandler.kt create mode 100644 triggers/timer/src/commonMain/kotlin/TimersRepo.kt create mode 100644 triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index f34b0f5..56c2fd8 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -4,8 +4,11 @@ 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.plaguposter.common.SuccessfulSymbol +import dev.inmo.plaguposter.posts.models.Post import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.tgbotapi.extensions.api.answers.answer 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 @@ -38,7 +41,9 @@ object ButtonsBuilder { dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis") } - suspend fun BehaviourContext.includeKeyboardHandling() { + suspend fun BehaviourContext.includeKeyboardHandling( + onSavePublishingTime: suspend (PostId, DateTime) -> Boolean + ) { fun buildKeyboard( prefix: String, postId: PostId, @@ -180,5 +185,21 @@ object ButtonsBuilder { oldDateTime.offset ) } + + onMessageDataCallbackQuery(Regex("$changeDateDataPrefix .*")) { + val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ") + val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery + val currentDateTime = DateTime(currentMillis) + val postId = PostId(rawPostId) + + val success = runCatchingSafely { + onSavePublishingTime(postId, currentDateTime) + }.getOrElse { false } + + answer( + it, + if (success) "Successfully set timer" else "Unable to set timer" + ) + } } } diff --git a/triggers/timer/src/commonMain/kotlin/TimersHandler.kt b/triggers/timer/src/commonMain/kotlin/TimersHandler.kt new file mode 100644 index 0000000..074108a --- /dev/null +++ b/triggers/timer/src/commonMain/kotlin/TimersHandler.kt @@ -0,0 +1,57 @@ +package dev.inmo.plaguposter.triggers.timer + +import com.soywiz.klock.DateTime +import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.plus +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.repos.unset +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.plaguposter.posts.sending.PostPublisher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +class TimersHandler( + private val timersRepo: TimersRepo, + private val publisher: PostPublisher, + private val scope: CoroutineScope +) { + private var currentPostAndJob: Pair? = null + private val currentJobMutex = Mutex() + + init { + (flowOf(Unit) + timersRepo.onNewValue + timersRepo.onValueRemoved).subscribeSafelyWithoutExceptions(scope) { + refreshPublishingJob() + } + } + + private suspend fun refreshPublishingJob() { + val minimal = timersRepo.getMinimalDateTimePost() + + currentJobMutex.withLock { + if (minimal ?.first == currentPostAndJob ?.first) { + return@withLock + } + + currentPostAndJob ?.second ?.cancel() + + currentPostAndJob = minimal ?.let { (postId, dateTime) -> + postId to scope.launchSafelyWithoutExceptions { + val now = DateTime.now() + val span = dateTime - now + + delay(span.millisecondsLong) + + publisher.publish(postId) + + timersRepo.unset(postId) + + refreshPublishingJob() + } + } + } + } +} diff --git a/triggers/timer/src/commonMain/kotlin/TimersRepo.kt b/triggers/timer/src/commonMain/kotlin/TimersRepo.kt new file mode 100644 index 0000000..f87dd6c --- /dev/null +++ b/triggers/timer/src/commonMain/kotlin/TimersRepo.kt @@ -0,0 +1,9 @@ +package dev.inmo.plaguposter.triggers.timer + +import com.soywiz.klock.DateTime +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.plaguposter.posts.models.PostId + +interface TimersRepo : KeyValueRepo { + suspend fun getMinimalDateTimePost(): Pair? +} diff --git a/triggers/timer/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/src/jvmMain/kotlin/Plugin.kt index f0ebf38..d4f719b 100644 --- a/triggers/timer/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/timer/src/jvmMain/kotlin/Plugin.kt @@ -2,8 +2,10 @@ package dev.inmo.plaguposter.triggers.timer import com.soywiz.klock.DateTime import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.repos.set import dev.inmo.plagubot.Plugin import dev.inmo.plaguposter.posts.repo.ReadPostsRepo +import dev.inmo.plaguposter.triggers.timer.repo.ExposedTimersRepo import dev.inmo.tgbotapi.extensions.api.edit.edit import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext @@ -12,15 +14,22 @@ import kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database import org.koin.core.Koin import org.koin.core.module.Module +import org.koin.dsl.binds 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()) } } override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { val postsRepo = koin.get() + val timersRepo = koin.get() with(ButtonsBuilder) { - includeKeyboardHandling() + includeKeyboardHandling { postId, dateTime -> + timersRepo.set(postId, dateTime) + true + } } onCommand("test") { val reply = it.replyTo ?: return@onCommand diff --git a/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt b/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt new file mode 100644 index 0000000..425070c --- /dev/null +++ b/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt @@ -0,0 +1,62 @@ +package dev.inmo.plaguposter.triggers.timer.repo + +import com.soywiz.klock.DateTime +import dev.inmo.micro_utils.common.firstNotNull +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.pagination.paginate +import dev.inmo.micro_utils.repos.exposed.initTable +import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo +import dev.inmo.micro_utils.repos.unset +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.plaguposter.posts.repo.PostsRepo +import dev.inmo.plaguposter.triggers.timer.TimersRepo +import kotlinx.coroutines.CoroutineScope +import org.jetbrains.exposed.sql.Column +import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.ISqlExpressionBuilder +import org.jetbrains.exposed.sql.Op +import org.jetbrains.exposed.sql.ResultRow +import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.statements.InsertStatement +import org.jetbrains.exposed.sql.statements.UpdateBuilder +import org.jetbrains.exposed.sql.transactions.transaction + +class ExposedTimersRepo( + database: Database, + postsRepo: PostsRepo, + scope: CoroutineScope +) : TimersRepo, AbstractExposedKeyValueRepo( + database, + "timers" +) { + override val keyColumn = text("post_id") + private val dateTimeColumn = long("date_time") + override val selectById: ISqlExpressionBuilder.(PostId) -> Op = { keyColumn.eq(it.string) } + override val selectByValue: ISqlExpressionBuilder.(DateTime) -> Op = { dateTimeColumn.eq(it.unixMillisLong) } + override val ResultRow.asKey: PostId + get() = PostId(get(keyColumn)) + override val ResultRow.asObject: DateTime + get() = DateTime(get(dateTimeColumn)) + + val postsRepoListeningJob = postsRepo.deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(scope) { + unset(it) + } + + init { + initTable() + } + + override fun update(k: PostId, v: DateTime, it: UpdateBuilder) { + it[dateTimeColumn] = v.unixMillisLong + } + + override fun insertKey(k: PostId, v: DateTime, it: InsertStatement) { + it[keyColumn] = k.string + } + + override suspend fun getMinimalDateTimePost(): Pair? = transaction(database) { + selectAll().orderBy(dateTimeColumn).limit(1).firstOrNull() ?.let { + PostId(it[keyColumn]) to DateTime(it[dateTimeColumn]) + } + } +} From b9c78982b50df5e6b77af69f2085dfb0a2e59c89 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 11:50:02 +0600 Subject: [PATCH 08/14] complete timer plugin --- common/src/commonMain/kotlin/ChatConfig.kt | 20 +++- common/src/jvmMain/kotlin/CommonPlugin.kt | 10 ++ .../kotlin/sending/PostPublisher.kt | 4 +- ratings/source/src/jvmMain/kotlin/Plugin.kt | 3 +- .../kotlin/exposed/ExposedRatingsRepo.kt | 5 + runner/build.gradle | 2 + settings.gradle | 2 + .../src/commonMain/kotlin/AutopostFilter.kt | 8 ++ .../src/jvmMain/kotlin/Plugin.kt | 9 +- triggers/timer/build.gradle | 1 + .../timer/disablers/autoposts/build.gradle | 18 +++ .../src/commonMain/kotlin/PackageInfo.kt | 1 + .../autoposts/src/jvmMain/kotlin/Plugin.kt | 27 +++++ .../autoposts/src/main/AndroidManifest.xml | 1 + triggers/timer/disablers/ratings/build.gradle | 18 +++ .../src/commonMain/kotlin/PackageInfo.kt | 1 + .../ratings/src/jvmMain/kotlin/Plugin.kt | 26 ++++ .../ratings/src/main/AndroidManifest.xml | 1 + .../src/commonMain/kotlin/ButtonsBuilder.kt | 112 ++++++++++++++---- .../kotlin/NearestAvailablePublishingTime.kt | 9 ++ .../src/commonMain/kotlin/TimerPanelButton.kt | 28 +++++ triggers/timer/src/jvmMain/kotlin/Plugin.kt | 50 ++++---- 22 files changed, 304 insertions(+), 52 deletions(-) create mode 100644 triggers/selector_with_timer/src/commonMain/kotlin/AutopostFilter.kt create mode 100644 triggers/timer/disablers/autoposts/build.gradle create mode 100644 triggers/timer/disablers/autoposts/src/commonMain/kotlin/PackageInfo.kt create mode 100644 triggers/timer/disablers/autoposts/src/jvmMain/kotlin/Plugin.kt create mode 100644 triggers/timer/disablers/autoposts/src/main/AndroidManifest.xml create mode 100644 triggers/timer/disablers/ratings/build.gradle create mode 100644 triggers/timer/disablers/ratings/src/commonMain/kotlin/PackageInfo.kt create mode 100644 triggers/timer/disablers/ratings/src/jvmMain/kotlin/Plugin.kt create mode 100644 triggers/timer/disablers/ratings/src/main/AndroidManifest.xml create mode 100644 triggers/timer/src/commonMain/kotlin/NearestAvailablePublishingTime.kt create mode 100644 triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt 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) } } } From bc0324a34f3fdbf4e3023b2ea6fca3fb0e2cda42 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 12:09:20 +0600 Subject: [PATCH 09/14] small fixes --- triggers/timer/src/jvmMain/kotlin/Plugin.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/triggers/timer/src/jvmMain/kotlin/Plugin.kt b/triggers/timer/src/jvmMain/kotlin/Plugin.kt index 088c278..f305c53 100644 --- a/triggers/timer/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/timer/src/jvmMain/kotlin/Plugin.kt @@ -2,11 +2,13 @@ package dev.inmo.plaguposter.triggers.timer import com.soywiz.klock.DateTime import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions 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.panel.PanelButtonsAPI import dev.inmo.plaguposter.posts.repo.ReadPostsRepo import dev.inmo.plaguposter.triggers.timer.repo.ExposedTimersRepo import dev.inmo.tgbotapi.extensions.api.answers.answer @@ -16,6 +18,7 @@ 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.coroutines.CoroutineScope import kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database import org.koin.core.Koin @@ -32,12 +35,23 @@ object Plugin : Plugin { override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { val timersRepo = koin.get() val chatsConfig = koin.get() + val panelApi = koin.get() + val scope = koin.get() with(ButtonsBuilder) { includeKeyboardHandling(timersRepo) { postId, dateTime -> timersRepo.set(postId, dateTime) true } } + + timersRepo.onNewValue.subscribeSafelyWithoutExceptions(scope) { + panelApi.forceRefresh(it.first) + } + + timersRepo.onValueRemoved.subscribeSafelyWithoutExceptions(scope) { + panelApi.forceRefresh(it) + } + onMessageDataCallbackQuery( Regex("${TimerPanelButton.timerSetPrefix} [^\\s]+"), initialFilter = { From 8899fb299f13625d09f0f8e5ef1d89df0c941be5 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 12:10:21 +0600 Subject: [PATCH 10/14] actualize sample onfig --- runner/config.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/runner/config.json b/runner/config.json index 4ba4f3a..1ef0bf4 100644 --- a/runner/config.json +++ b/runner/config.json @@ -7,15 +7,19 @@ }, "botToken": "1234567890:ABCDEFGHIJKLMNOP_qrstuvwxyz12345678", "plugins": [ - "dev.inmo.plagubot.plugins.inline.queries.Plugin", "dev.inmo.plaguposter.posts.Plugin", "dev.inmo.plaguposter.posts.registrar.Plugin", "dev.inmo.plaguposter.ratings.Plugin", "dev.inmo.plaguposter.ratings.source.Plugin", "dev.inmo.plaguposter.ratings.selector.Plugin", "dev.inmo.plaguposter.triggers.selector_with_timer.Plugin", + "dev.inmo.plagubot.plugins.inline.queries.Plugin", "dev.inmo.plaguposter.triggers.command.Plugin", - "dev.inmo.plaguposter.posts.panel.Plugin" + "dev.inmo.plaguposter.posts.panel.Plugin", + "dev.inmo.plaguposter.common.CommonPlugin", + "dev.inmo.plaguposter.triggers.timer.Plugin", + "dev.inmo.plaguposter.triggers.timer.disablers.ratings.Plugin", + "dev.inmo.plaguposter.triggers.timer.disablers.autoposts.Plugin" ], "posts": { "chats": { From 2baaac8e6d118349a01426486131f583109423d8 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 16:38:14 +0600 Subject: [PATCH 11/14] add several supporting hints --- .../src/commonMain/kotlin/ButtonsBuilder.kt | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index f1db4f4..ee0ac44 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -43,15 +43,15 @@ object ButtonsBuilder { ) = inlineKeyboard { val unixMillis = dateTime.utc.unixMillisLong row { - dataButton("Time:", changeTimeData) + dataButton("Time (hh:mm):", 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("Date (dd.mm.yyyy):", changeDateData) + dataButton("${dateTime.dayOfMonth}", "$changeDayDataPrefix $postId $unixMillis") + dataButton("${dateTime.month1}", "$changeMonthDataPrefix $postId $unixMillis") + dataButton("${dateTime.yearInt}", "$changeYearDataPrefix $postId $unixMillis") } row { @@ -96,6 +96,7 @@ object ButtonsBuilder { } suspend fun buildStandardDataCallbackQuery( + name: String, prefix: String, possibleValues: (DateTimeTz) -> Iterable, dateTimeConverter: (Int, DateTimeTz) -> DateTimeTz @@ -104,18 +105,24 @@ object ButtonsBuilder { onMessageDataCallbackQuery(Regex("$prefix .+")) { val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ") val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery - val currentDateTime = DateTime(currentMillis).local + val currentDateTime = DateTime(currentMillis) + val currentDateTimeLocal = DateTime(currentMillis).local + val postId = PostId(rawPostId) + val previousTime = timersRepo.get(postId) edit ( - it.message, + it.message.withContentOrNull() ?: return@onMessageDataCallbackQuery, replyMarkup = buildKeyboard( setPrefix, - PostId(rawPostId), - possibleValues(currentDateTime) + postId, + possibleValues(currentDateTimeLocal) ) { - dateTimeConverter(it, currentDateTime) + dateTimeConverter(it, currentDateTimeLocal) } - ) + ) { + +buildTimerTextSources(currentDateTime, previousTime) + "\n" + +"You are about to edit $name" + } } onMessageDataCallbackQuery(Regex("$setPrefix .+")) { @@ -141,6 +148,7 @@ object ButtonsBuilder { fun DateTimeTz.dateEq(other: DateTimeTz) = yearInt == other.yearInt && month0 == other.month0 && dayOfMonth == other.dayOfMonth buildStandardDataCallbackQuery( + "hour", changeHoursDataPrefix, { val now = nearestAvailableTimerTime().local @@ -159,6 +167,7 @@ object ButtonsBuilder { } buildStandardDataCallbackQuery( + "minute", changeMinutesDataPrefix, { val now = nearestAvailableTimerTime().local @@ -177,6 +186,7 @@ object ButtonsBuilder { } buildStandardDataCallbackQuery( + "day", changeDayDataPrefix, { val now = nearestAvailableTimerTime().local @@ -195,6 +205,7 @@ object ButtonsBuilder { } buildStandardDataCallbackQuery( + "month", changeMonthDataPrefix, { val now = nearestAvailableTimerTime().local @@ -213,6 +224,7 @@ object ButtonsBuilder { } buildStandardDataCallbackQuery( + "year", changeYearDataPrefix, { val now = nearestAvailableTimerTime().local From 5f65095698ee4d77c370cea7d7674dc65312c89d Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 16:45:06 +0600 Subject: [PATCH 12/14] hotfix --- triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt index ee0ac44..efb2d30 100644 --- a/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt +++ b/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt @@ -34,7 +34,7 @@ object ButtonsBuilder { 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") + val datePrintFormat = DateFormat("HH:mm, dd.MM.yyyy, zzz") fun buildTimerButtons( postId: PostId, From 01b9d0b2aba62d0335fc4f4aa800797184850a81 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Dec 2022 23:20:35 +0600 Subject: [PATCH 13/14] experimental fix of krontab --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cef955b..7fd603f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ plagubot = "3.2.1" tgbotapi = "4.2.1" microutils = "0.16.1" kslog = "0.5.4" -krontab = "0.8.4" +krontab = "0.8.5-branch_0.8.5-build159" tgbotapi-libraries = "0.6.5" plagubot-plugins = "0.6.4" From b453401c33cfbd8b324e5514fd5fa16a5dd2834f Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 15 Dec 2022 10:37:48 +0600 Subject: [PATCH 14/14] Update libs.versions.toml --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7fd603f..4f56f66 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ plagubot = "3.2.1" tgbotapi = "4.2.1" microutils = "0.16.1" kslog = "0.5.4" -krontab = "0.8.5-branch_0.8.5-build159" +krontab = "0.8.5" tgbotapi-libraries = "0.6.5" plagubot-plugins = "0.6.4"