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 @@ +