add Morny CRONs

This commit is contained in:
A.C.Sukazyo Eyre 2024-05-21 17:04:12 +08:00
parent a62398e0c5
commit 2baa249d63
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
5 changed files with 140 additions and 1 deletions

View File

@ -367,7 +367,6 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
* }}}
*/
object dsl extends BotExtension {
given coeur: MornyCoeur = MornyCoeur.this
given account: TelegramBot = MornyCoeur.this.account
given translations: MornyLangs = MornyCoeur.this.lang
}

View File

@ -4,10 +4,44 @@ import cc.sukazyo.cono.morny.core.MornyCoeur.*
trait MornyModule {
/** The unique id of this Morny module.
*
* Requires to be unique between modules that will loaded, requires only contains ASCII
* characters excepts control characters.
*
* This module id will listed in the module lists as the primary key. Although currently
* is no checks to make sure this is unique (and if is legal), it is still highly
* recommended making this unique between modules, for forward compatibles and third-party
* compatibles.
*
* Recommended to be named using all lowercased characters and hyphen character (`-`) like
* `module-author-or-provider.module-name` . For example, the Morny internal module
* `morny_misc` has the id `morny.misc`, and `stickers_get` has the id `morny.stickers-get`.
*/
val id: String
/** Human readable name of this Morny module.
*
* No specific formats requires except do not contains ASCII control characters.
*
* No special usage except showing in module table.
*
* Recommended set this to a English name while the i18n for this is not implemented yet.
*/
val name: String
/** Version of this module build.
*
* No special usage except showing in module table.
*/
val version: String
/** Human readable description of this Morny module.
*
* Should be a Markdown document.
*
* No special usage.
*
* Recommended to use English while the i18n for this is not implemented yet.
*/
val description: String | Null
def onInitializingPre (using MornyCoeur)(cxt: OnInitializingPreContext): Unit = {}

View File

@ -13,6 +13,7 @@ object ServerModulesLoader {
morny.slash_action.ModuleSlashAction(),
morny.nbnhhsh.ModuleNbnhhsh(),
morny.ip186.ModuleIP186(),
morny.crons.ModuleCRONs(),
morny.encrypt_tool.ModuleEncryptor(),
morny.call_me.ModuleCallMe(),
morny.social_share.ModuleSocialShare(),

View File

@ -0,0 +1,24 @@
package cc.sukazyo.cono.morny.crons
import cc.sukazyo.cono.morny.core.internal.MornyInternalModule
import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.crons.cmd.CommandCreate
class ModuleCRONs extends MornyInternalModule {
override val id: String = "morny.cron"
override val name: String = "Morny CRON messaging for Users"
override val description: String | Null =
// language=markdown
"""Provides users to set CRON based timer for messaging to themselves.
|
|Not implemented yet while Morny's database is not implemented yet.""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.commandManager
commandManager `register` CommandCreate()
}
}

View File

@ -0,0 +1,81 @@
package cc.sukazyo.cono.morny.crons.cmd
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
import com.cronutils.descriptor.CronDescriptor
import com.cronutils.model.{Cron, CronType}
import com.cronutils.model.definition.CronDefinitionBuilder
import com.cronutils.model.time.ExecutionTime
import com.cronutils.parser.CronParser
import com.pengrad.telegrambot.model.{Message, Update}
import com.pengrad.telegrambot.request.{SendMessage, SendSticker}
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
class CommandCreate (using coeur: MornyCoeur) extends ISimpleCommand {
import coeur.dsl.{*, given}
override val name: String = "create_cron_message"
override val aliases: List[ICommandAlias] = Nil
override def execute (using command: InputCommand, event: Update): Unit = {
given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using event.message)
SendMessage(
context.bind_chat.id,
"Type your CRON expression below:"
).replyToMessageId(context.bind_message.messageId)
.unsafeExecute
coeur.messageThreading.doAfter(execute1)
}
def execute1 (message: Message, prev: MessagingContext.WithUserAndMessage): Unit = {
given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using message)
val cron: Cron =
try CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX))
.parse(message.text())
catch case e: IllegalArgumentException =>
ErrorMessage(
SendSticker(
context.bind_chat.id,
TelegramStickers.ID_404
),
SendMessage(
context.bind_chat.id,
s"""Probably you've entered an invalid CRON expression:
|
|${e.toLogString}
|""".stripMargin
)
).submit
return
val cron_describe = CronDescriptor.instance().describe(cron)
val current = ZonedDateTime.now()
val cron_exec_time = ExecutionTime.forCron(cron)
val cron_next = cron_exec_time.nextExecution(current)
val cron_prev = cron_exec_time.lastExecution(current)
SendMessage(
context.bind_chat.id,
s"""Set CRON task.
|
|Your cron settings is runs $cron_describe
|Previous runs at: ${cron_prev.map(_.format(DateTimeFormatter.ISO_DATE_TIME)).orElse("Will not run before.")}
|Next will run at: ${cron_next.map(_.format(DateTimeFormatter.ISO_DATE_TIME)).orElse("Will not run afterwards.")}
|
|""".stripMargin
).replyToMessageId(context.bind_message.messageId)
.unsafeExecute
}
}