PlaguPoster/triggers/timer/src/commonMain/kotlin/ButtonsBuilder.kt

288 lines
10 KiB
Kotlin
Raw Normal View History

2022-12-13 06:32:18 +00:00
package dev.inmo.plaguposter.triggers.timer
2022-12-14 05:50:02 +00:00
import com.soywiz.klock.DateFormat
2022-12-13 06:32:18 +00:00
import com.soywiz.klock.DateTime
import com.soywiz.klock.DateTimeTz
import com.soywiz.klock.Month
2022-12-13 06:41:30 +00:00
import com.soywiz.klock.Year
2022-12-14 03:43:12 +00:00
import dev.inmo.micro_utils.coroutines.runCatchingSafely
2022-12-14 05:50:02 +00:00
import dev.inmo.micro_utils.repos.unset
2022-12-13 06:32:18 +00:00
import dev.inmo.plaguposter.common.SuccessfulSymbol
2022-12-14 05:50:02 +00:00
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
2022-12-13 06:32:18 +00:00
import dev.inmo.plaguposter.posts.models.PostId
2022-12-14 03:43:12 +00:00
import dev.inmo.tgbotapi.extensions.api.answers.answer
2022-12-14 05:50:02 +00:00
import dev.inmo.tgbotapi.extensions.api.delete
2022-12-13 06:32:18 +00:00
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.inlineKeyboard
2022-12-14 05:50:02 +00:00
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
2022-12-13 06:32:18 +00:00
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
2022-12-14 05:50:02 +00:00
import dev.inmo.tgbotapi.utils.bold
import dev.inmo.tgbotapi.utils.buildEntities
2022-12-13 06:32:18 +00:00
import dev.inmo.tgbotapi.utils.row
object ButtonsBuilder {
2022-12-14 05:50:02 +00:00
private const val changeTimeData = "timer_time_hint"
private const val changeDateData = "timer_date_hint"
2022-12-13 07:16:55 +00:00
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"
2022-12-14 05:50:02 +00:00
private const val cancelDateData = "timer_c"
private const val deleteDateDataPrefix = "timer_r"
2022-12-14 10:45:06 +00:00
val datePrintFormat = DateFormat("HH:mm, dd.MM.yyyy, zzz")
2022-12-13 07:16:55 +00:00
fun buildTimerButtons(
2022-12-13 06:32:18 +00:00
postId: PostId,
2022-12-14 05:50:02 +00:00
dateTime: DateTimeTz,
exists: Boolean
) = inlineKeyboard {
2022-12-13 07:16:55 +00:00
val unixMillis = dateTime.utc.unixMillisLong
2022-12-14 05:50:02 +00:00
row {
2022-12-14 10:38:14 +00:00
dataButton("Time (hh:mm):", changeTimeData)
2022-12-14 05:50:02 +00:00
dataButton(dateTime.hours.toString(), "$changeHoursDataPrefix $postId $unixMillis")
dataButton(dateTime.minutes.toString(), "$changeMinutesDataPrefix $postId $unixMillis")
}
row {
2022-12-14 10:38:14 +00:00
dataButton("Date (dd.mm.yyyy):", changeDateData)
dataButton("${dateTime.dayOfMonth}", "$changeDayDataPrefix $postId $unixMillis")
dataButton("${dateTime.month1}", "$changeMonthDataPrefix $postId $unixMillis")
dataButton("${dateTime.yearInt}", "$changeYearDataPrefix $postId $unixMillis")
2022-12-14 05:50:02 +00:00
}
2022-12-13 06:32:18 +00:00
2022-12-14 05:50:02 +00:00
row {
if (exists) {
dataButton("\uD83D\uDDD1", "$deleteDateDataPrefix $postId")
}
dataButton(UnsuccessfulSymbol, cancelDateData)
dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis")
}
}
2022-12-13 06:32:18 +00:00
2022-12-14 05:50:02 +00:00
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))
2022-12-13 06:32:18 +00:00
}
2022-12-14 03:43:12 +00:00
suspend fun BehaviourContext.includeKeyboardHandling(
2022-12-14 05:50:02 +00:00
timersRepo: TimersRepo,
2022-12-14 03:43:12 +00:00
onSavePublishingTime: suspend (PostId, DateTime) -> Boolean
) {
2022-12-13 06:32:18 +00:00
fun buildKeyboard(
prefix: String,
postId: PostId,
values: Iterable<Int>,
2022-12-14 05:50:02 +00:00
min: DateTime = nearestAvailableTimerTime(),
2022-12-13 07:16:55 +00:00
dateConverter: (Int) -> DateTimeTz
2022-12-13 06:32:18 +00:00
): InlineKeyboardMarkup {
return inlineKeyboard {
2022-12-13 08:00:13 +00:00
values.chunked(6).forEach {
2022-12-13 06:32:18 +00:00
row {
it.forEach {
2022-12-13 07:16:55 +00:00
dataButton(it.toString(), "$prefix $postId ${dateConverter(it).utc.unixMillisLong.coerceAtLeast(min.unixMillisLong)}")
2022-12-13 06:32:18 +00:00
}
}
}
}
}
suspend fun buildStandardDataCallbackQuery(
2022-12-14 10:38:14 +00:00
name: String,
2022-12-13 06:32:18 +00:00
prefix: String,
2022-12-13 07:16:55 +00:00
possibleValues: (DateTimeTz) -> Iterable<Int>,
dateTimeConverter: (Int, DateTimeTz) -> DateTimeTz
2022-12-13 06:32:18 +00:00
) {
2022-12-13 07:16:55 +00:00
val setPrefix = "${prefix}s"
2022-12-13 06:32:18 +00:00
onMessageDataCallbackQuery(Regex("$prefix .+")) {
val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ")
val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery
2022-12-14 10:38:14 +00:00
val currentDateTime = DateTime(currentMillis)
val currentDateTimeLocal = DateTime(currentMillis).local
val postId = PostId(rawPostId)
val previousTime = timersRepo.get(postId)
2022-12-13 06:32:18 +00:00
edit (
2022-12-14 10:38:14 +00:00
it.message.withContentOrNull() ?: return@onMessageDataCallbackQuery,
2022-12-13 06:32:18 +00:00
replyMarkup = buildKeyboard(
setPrefix,
2022-12-14 10:38:14 +00:00
postId,
possibleValues(currentDateTimeLocal)
2022-12-13 06:32:18 +00:00
) {
2022-12-14 10:38:14 +00:00
dateTimeConverter(it, currentDateTimeLocal)
2022-12-13 06:32:18 +00:00
}
2022-12-14 10:38:14 +00:00
) {
+buildTimerTextSources(currentDateTime, previousTime) + "\n"
+"You are about to edit $name"
}
2022-12-13 06:32:18 +00:00
}
onMessageDataCallbackQuery(Regex("$setPrefix .+")) {
val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ")
val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery
val currentDateTime = DateTime(currentMillis)
2022-12-14 05:50:02 +00:00
val postId = PostId(rawPostId)
val previousTime = timersRepo.get(postId)
2022-12-13 06:32:18 +00:00
edit(
2022-12-14 05:50:02 +00:00
it.message.withContentOrNull() ?: return@onMessageDataCallbackQuery,
replyMarkup = buildTimerButtons(
postId,
currentDateTime.local,
timersRepo.contains(postId)
2022-12-13 06:32:18 +00:00
)
2022-12-14 05:50:02 +00:00
) {
+buildTimerTextSources(currentDateTime, previousTime)
}
2022-12-13 06:32:18 +00:00
}
}
2022-12-13 06:39:32 +00:00
fun DateTimeTz.dateEq(other: DateTimeTz) = yearInt == other.yearInt && month0 == other.month0 && dayOfMonth == other.dayOfMonth
2022-12-13 06:32:18 +00:00
buildStandardDataCallbackQuery(
2022-12-14 10:38:14 +00:00
"hour",
2022-12-13 06:32:18 +00:00
changeHoursDataPrefix,
2022-12-13 06:39:32 +00:00
{
2022-12-14 05:50:02 +00:00
val now = nearestAvailableTimerTime().local
2022-12-13 06:39:32 +00:00
2022-12-13 07:16:55 +00:00
if (now.dateEq(it)) {
2022-12-13 06:39:32 +00:00
now.hours .. 23
} else {
0 .. 23
}
}
2022-12-13 06:32:18 +00:00
) { newValue, oldDateTime ->
2022-12-13 07:16:55 +00:00
DateTimeTz.local(
oldDateTime.local.copyDayOfMonth(hours = newValue),
oldDateTime.offset
)
2022-12-13 06:32:18 +00:00
}
buildStandardDataCallbackQuery(
2022-12-14 10:38:14 +00:00
"minute",
2022-12-13 06:32:18 +00:00
changeMinutesDataPrefix,
2022-12-13 06:39:32 +00:00
{
2022-12-14 05:50:02 +00:00
val now = nearestAvailableTimerTime().local
2022-12-13 06:39:32 +00:00
2022-12-13 07:16:55 +00:00
if (now.dateEq(it) && now.hours >= it.hours) {
now.minutes until 60
2022-12-13 06:39:32 +00:00
} else {
2022-12-13 07:16:55 +00:00
0 until 60
2022-12-13 06:39:32 +00:00
}
}
2022-12-13 06:32:18 +00:00
) { newValue, oldDateTime ->
2022-12-13 07:16:55 +00:00
DateTimeTz.local(
oldDateTime.local.copyDayOfMonth(minutes = newValue),
oldDateTime.offset
)
2022-12-13 06:32:18 +00:00
}
buildStandardDataCallbackQuery(
2022-12-14 10:38:14 +00:00
"day",
2022-12-13 06:32:18 +00:00
changeDayDataPrefix,
{
2022-12-14 05:50:02 +00:00
val now = nearestAvailableTimerTime().local
2022-12-13 06:32:18 +00:00
2022-12-13 07:16:55 +00:00
if (now.yearInt == it.yearInt && now.month0 == it.month0) {
2022-12-13 06:39:32 +00:00
now.dayOfMonth .. it.month.days(it.year)
} else {
1 .. it.month.days(it.year)
}
}
2022-12-13 06:32:18 +00:00
) { newValue, oldDateTime ->
2022-12-13 07:16:55 +00:00
DateTimeTz.local(
oldDateTime.local.copyDayOfMonth(dayOfMonth = newValue),
oldDateTime.offset
)
2022-12-13 06:32:18 +00:00
}
buildStandardDataCallbackQuery(
2022-12-14 10:38:14 +00:00
"month",
2022-12-13 06:32:18 +00:00
changeMonthDataPrefix,
2022-12-13 06:39:32 +00:00
{
2022-12-14 05:50:02 +00:00
val now = nearestAvailableTimerTime().local
2022-12-13 06:39:32 +00:00
2022-12-13 07:16:55 +00:00
if (now.year == it.year) {
2022-12-13 06:39:32 +00:00
now.month1 .. 12
} else {
1 .. 12
}
}
2022-12-13 06:32:18 +00:00
) { newValue, oldDateTime ->
2022-12-13 07:16:55 +00:00
DateTimeTz.local(
oldDateTime.local.copyDayOfMonth(month = Month(newValue)),
oldDateTime.offset
)
2022-12-13 06:32:18 +00:00
}
buildStandardDataCallbackQuery(
2022-12-14 10:38:14 +00:00
"year",
2022-12-13 06:32:18 +00:00
changeYearDataPrefix,
{
2022-12-14 05:50:02 +00:00
val now = nearestAvailableTimerTime().local
(now.year.year .. (now.year.year + 5))
2022-12-13 06:32:18 +00:00
}
) { newValue, oldDateTime ->
2022-12-13 07:16:55 +00:00
DateTimeTz.local(
oldDateTime.local.copyDayOfMonth(year = Year(newValue)),
oldDateTime.offset
)
2022-12-13 06:32:18 +00:00
}
2022-12-14 03:43:12 +00:00
2022-12-14 05:50:02 +00:00
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)
}
2022-12-14 03:43:12 +00:00
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"
)
2022-12-14 05:50:02 +00:00
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)
2022-12-14 03:43:12 +00:00
}
2022-12-13 06:32:18 +00:00
}
}