diff --git a/project/MornyConfiguration.scala b/project/MornyConfiguration.scala
index 6ec9177..1ba7f21 100644
--- a/project/MornyConfiguration.scala
+++ b/project/MornyConfiguration.scala
@@ -16,28 +16,28 @@ object MornyConfiguration {
val dependencies: Seq[ModuleID] = Seq(
- "com.github.spotbugs" % "spotbugs-annotations" % "4.7.3" % Compile,
+ "com.github.spotbugs" % "spotbugs-annotations" % "4.8.2" % Compile,
"cc.sukazyo" % "messiva" % "0.2.0",
"cc.sukazyo" % "resource-tools" % "0.2.2",
"com.github.pengrad" % "java-telegram-bot-api" % "6.2.0",
- "org.http4s" %% "http4s-dsl" % "0.23.24",
- "org.http4s" %% "http4s-circe" % "0.23.24",
- "org.http4s" %% "http4s-netty-server" % "0.5.11",
+ "org.http4s" %% "http4s-dsl" % "0.23.25",
+ "org.http4s" %% "http4s-circe" % "0.23.25",
+ "org.http4s" %% "http4s-netty-server" % "0.5.12",
- "com.softwaremill.sttp.client3" %% "core" % "3.9.0",
- "com.softwaremill.sttp.client3" %% "okhttp-backend" % "3.9.0",
- "com.squareup.okhttp3" % "okhttp" % "4.11.0" % Runtime,
+ "com.softwaremill.sttp.client3" %% "core" % "3.9.2",
+ "com.softwaremill.sttp.client3" %% "okhttp-backend" % "3.9.2",
+ "com.squareup.okhttp3" % "okhttp" % "4.12.0" % Runtime,
"org.typelevel" %% "case-insensitive" % "1.4.0",
"com.google.code.gson" % "gson" % "2.10.1",
"io.circe" %% "circe-core" % "0.14.6",
"io.circe" %% "circe-generic" % "0.14.6",
"io.circe" %% "circe-parser" % "0.14.6",
- "org.jsoup" % "jsoup" % "1.16.2",
+ "org.jsoup" % "jsoup" % "1.17.2",
- "com.cronutils" % "cron-utils" % "9.2.0",
+ "com.cronutils" % "cron-utils" % "9.2.1",
// used for disable slf4j
// due to the slf4j api have been used in the following libraries:
@@ -47,8 +47,8 @@ object MornyConfiguration {
"org.scalatest" %% "scalatest" % "3.2.17" % Test,
"org.scalatest" %% "scalatest-freespec" % "3.2.17" % Test,
// for test report
- "com.vladsch.flexmark" % "flexmark" % "0.64.0" % Test,
- "com.vladsch.flexmark" % "flexmark-profile-pegdown" % "0.64.0" % Test
+ "com.vladsch.flexmark" % "flexmark" % "0.64.8" % Test,
+ "com.vladsch.flexmark" % "flexmark-profile-pegdown" % "0.64.8" % Test
)
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala
index fdb5cc2..6647406 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/BotExtension.scala
@@ -12,8 +12,9 @@ object BotExtension {
/** Submit this [[ErrorMessage]] to a [[MornyCoeur]].
*
* Will send this [[ErrorMessage]] with the basic send config.
- *
+ *
* @see [[cc.sukazyo.cono.morny.core.bot.internal.ErrorMessageManager.sendErrorMessage]]
+ * @since 2.0.0
*/
def submit (using coeur: MornyCoeur): Unit =
coeur.errorMessageManager.sendErrorMessage(errorMessage)
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/EventEnv.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/EventEnv.scala
index 11dfb81..b36f9d2 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/EventEnv.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/EventEnv.scala
@@ -7,38 +7,77 @@ import com.pengrad.telegrambot.model.Update
import scala.collection.mutable
+/** A Telegram event context that holds status of the event.
+ *
+ * @param update Associated raw [[Update]] object.
+ */
class EventEnv (
val update: Update
) {
+ /** This status contains a [[StackTraceElement]] that shows where the status is set. */
trait StateSource (val from: StackTraceElement)
+ /** Available status of the event. */
enum State:
+ /** The event is successfully processed by someone event listener. */
case OK (_from: StackTraceElement) extends State with StateSource(_from)
+ /** The event is canceled for some reason, it is recommended be ignored. */
case CANCELED (_from: StackTraceElement) extends State with StateSource(_from)
private val _status: mutable.ListBuffer[State] = mutable.ListBuffer.empty
+ /** [[GivenContext Given Contexts]] associated to the event. Can be used to store and share
+ * data between event listeners.
+ * @since 1.3.0
+ */
val givenCxt: GivenContext = GivenContext()
+ /** The [[EpochMillis]] time that bot received this event and preparing to process it.
+ * @since 1.3.0
+ */
val timeStartup: EpochMillis = System.currentTimeMillis
+ /** If this event is processed.
+ *
+ * Not only [[State.OK]] but also [[State.CANCELED]] will been seen as processed.
+ *
+ * @since 1.2.0
+ *
+ * @return `true` if the event have been processed, `false` otherwise.
+ */
def isEventOk: Boolean = _status.lastOption match
case Some(x) if x == State.OK => true
case _ => false
+ /** Set the event status to [[State.OK]].
+ *
+ * This will push a new [[State.OK]] to the status list.
+ */
//noinspection UnitMethodIsParameterless
def setEventOk: Unit =
_status += State.OK(StackUtils.getStackTrace(1).head)
+ /** Set the event status to [[State.CANCELED]].
+ *
+ * This will push a new [[State.CANCELED]] to the status list.
+ *
+ * @since 1.3.0
+ */
//noinspection UnitMethodIsParameterless
def setEventCanceled: Unit =
_status += State.CANCELED(StackUtils.getStackTrace(1).head)
+ /** Get the last [[State]] set of the event.
+ * @since 1.3.0
+ */
def state: State|Null =
_status.lastOption match
case Some(x) => x
case None => null
+ /** Get all the status set of the event. The earlier status set is in the left.
+ * @since 1.3.0
+ */
def status: List[State] =
_status.toList
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/ErrorMessage.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/ErrorMessage.scala
index ee4ddb7..5257a0c 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/ErrorMessage.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/ErrorMessage.scala
@@ -37,6 +37,8 @@ trait ErrorMessage[T1 <: AbstractSendRequest[T1], T2 <: AbstractSendRequest[T2]]
* This method returns a union type [[T1]] and [[T2]]. This may be
* not useful when you don't care about the specific return types (maybe for
* the most times). You can use [[getByTypeNormal]] instead.
+ *
+ * @since 2.0.0
*/
def getByType (t: ErrorMessage.Types): AbstractSendRequest[T1] | AbstractSendRequest[T2] =
t match
@@ -49,6 +51,7 @@ trait ErrorMessage[T1 <: AbstractSendRequest[T1], T2 <: AbstractSendRequest[T2]]
* this returns with a bit universal type `AbstractSendRequest[?]`.
*
* @see [[getByType]]
+ * @since 2.0.0
*/
def getByTypeNormal (t: ErrorMessage.Types): AbstractSendRequest[?] =
getByType(t)
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/MessagingContext.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/MessagingContext.scala
index 7a70892..f080a33 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/MessagingContext.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/api/messages/MessagingContext.scala
@@ -69,6 +69,8 @@ object MessagingContext {
WithUserAndMessage(_chat, _user, _message)
/** Extract a message context from a message (or message event).
+ *
+ * @since 2.0.0
*
* @param message The message.
* @return The message context, contains the message's belongs chat, sender user and message itself.
diff --git a/src/main/scala/cc/sukazyo/cono/morny/core/bot/internal/ErrorMessageManager.scala b/src/main/scala/cc/sukazyo/cono/morny/core/bot/internal/ErrorMessageManager.scala
index 0472bcf..71f1115 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/core/bot/internal/ErrorMessageManager.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/core/bot/internal/ErrorMessageManager.scala
@@ -28,6 +28,8 @@ class ErrorMessageManager (using coeur: MornyCoeur) {
/** Send an [[ErrorMessage]] and add this error message to ErrorMessage stash.
*
* This will execute the SendRequest using the default send config.
+ *
+ * @since 2.0.0
*/
def sendErrorMessage (message: ErrorMessage[?, ?]): Unit =
// todo: which should be sent using user config
@@ -35,6 +37,8 @@ class ErrorMessageManager (using coeur: MornyCoeur) {
sendErrorMessage(message, useType, isNewMessage = true)
/** Send an [[ErrorMessage]] and add it to the stash if it is new.
+ *
+ * @since 2.0.0
*
* @param message The [[ErrorMessage]] to be sent.
* @param useType Which type of the message should be sent.
@@ -80,6 +84,8 @@ class ErrorMessageManager (using coeur: MornyCoeur) {
*
* Notice that one [[ErrorMessage]] will only be stashed for 5 hours then it will be
* cleaned up from the stash.
+ *
+ * @since 2.0.0
*/
def inspectMessage (messageKey: MessagingContext.WithMessage.Key): Option[ErrorMessage[?, ?]] =
errorMessageMap.get(messageKey)
diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramParseEscape.scala b/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramParseEscape.scala
index d8dccf7..980af68 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramParseEscape.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/formatting/TelegramParseEscape.scala
@@ -8,6 +8,13 @@ import scala.jdk.CollectionConverters.*
object TelegramParseEscape {
+ /** Encoded a [[String]] that make it can be used as plain texts in Telegram HTML.
+ *
+ * This method will just remove `&`, `<` and `>` characters and encode them to
+ * HTML entities.
+ *
+ * @since 1.0.0
+ */
def escapeHtml (input: String): String =
var process = input
process = process.replaceAll("&", "&")
@@ -15,6 +22,24 @@ object TelegramParseEscape {
process = process.replaceAll(">", ">")
process
+ /** Transform a [[String]] encoded HTML document/fragment into a Telegram capable
+ * HTML fragment, make it can be used in sending Telegram message etc.
+ *
+ * This method will remove all unsupported HTML tags and attributes. Here is the
+ * specific rule list of how to process the tags:
+ *
+ * - If the tag is supported by Telegram HTML, it will be kept, and the inner HTML
+ * children items will be processed recursively.
+ * - If the tag is `
`, it will be converted to a newline character (`\n`). If
+ * there's any children in the `
` tag (which is not allowed in HTML), they
+ * will just be ignored.
+ * - If the tag is ``, it will be removed. If the `alt` attribute is present,
+ * a string `"[$alt]"` will be used as the replacement text.
+ * - If the tag is any other tag, it will be removed, and the inner HTML children
+ * will be kept and processed recursively.
+ *
+ * @since 1.3.0
+ */
def cleanupHtml (input: String): String =
import org.jsoup.nodes.*
val source = Jsoup.parse(input)
@@ -32,7 +57,7 @@ object TelegramParseEscape {
// case _: (DataNode | XmlDeclaration | DocumentType | Comment) => ""
// case elem: Element => elem.childNodes.asScala.map(f => toHtmlRaw(f)).mkString("")
- def cleanupHtml (input: Seq[Node]): List[Node] =
+ private def cleanupHtml (input: Seq[Node]): List[Node] =
val result = mutable.ListBuffer.empty[Node]
for (i <- input) {
import org.jsoup.nodes.*