mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2025-02-21 21:58:50 +08:00
add TelegramBotEvents.{OnGetUpdateFailed, OnListenerOccursException}
- also add dependency da4a, change GivenContext to da4a version. - make MornyReport uses the above events to function, instead of calling MornyReport directly in Coeur.
This commit is contained in:
parent
bd95870864
commit
96101ec434
@ -8,8 +8,13 @@ ThisBuild / version := MornyProject.version
|
||||
ThisBuild / scalaVersion := "3.4.1"
|
||||
|
||||
ThisBuild / resolvers ++= Seq(
|
||||
"-ws-releases" at "https://mvn.sukazyo.cc/releases"
|
||||
)
|
||||
"-ws-releases" at "https://mvn.sukazyo.cc/releases",
|
||||
if (MornyProject.version_is_snapshot) {
|
||||
"-ws-snapshots" at "https://mvn.sukazyo.cc/snapshots"
|
||||
} else {
|
||||
null
|
||||
}
|
||||
).filter(x => x != null)
|
||||
|
||||
ThisBuild / crossPaths := false
|
||||
|
||||
|
@ -6,16 +6,16 @@ import cc.sukazyo.cono.morny.core.bot.api.{BotExtension, EventListenerManager, M
|
||||
import cc.sukazyo.cono.morny.core.bot.api.messages.ThreadingManager
|
||||
import cc.sukazyo.cono.morny.core.bot.event.{MornyOnInlineQuery, MornyOnTelegramCommand, MornyOnUpdateTimestampOffsetLock}
|
||||
import cc.sukazyo.cono.morny.core.bot.internal.{ErrorMessageManager, ThreadingManagerImpl}
|
||||
import cc.sukazyo.cono.morny.core.event.TelegramBotEvents
|
||||
import cc.sukazyo.cono.morny.core.http.api.{HttpServer, MornyHttpServerContext}
|
||||
import cc.sukazyo.cono.morny.core.http.internal.MornyHttpServerContextImpl
|
||||
import cc.sukazyo.cono.morny.core.module.ModuleHelper
|
||||
import cc.sukazyo.cono.morny.reporter.MornyReport
|
||||
import cc.sukazyo.cono.morny.system.utils.EpochDateTime.EpochMillis
|
||||
import cc.sukazyo.cono.morny.system.utils.GivenContext
|
||||
import cc.sukazyo.cono.morny.util.schedule.Scheduler
|
||||
import cc.sukazyo.cono.morny.util.time.WatchDog
|
||||
import cc.sukazyo.cono.morny.util.UseString.MString
|
||||
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
|
||||
import cc.sukazyo.std.contexts.GivenContext
|
||||
import com.pengrad.telegrambot.TelegramBot
|
||||
import com.pengrad.telegrambot.request.GetMe
|
||||
|
||||
@ -118,6 +118,8 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
||||
|
||||
given MornyCoeur = this
|
||||
|
||||
val telegramBotEvents = new TelegramBotEvents()
|
||||
|
||||
val externalContext: GivenContext = GivenContext()
|
||||
logger `info`
|
||||
m"""The following Modules have been added to current Morny:
|
||||
@ -150,7 +152,7 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
||||
|
||||
///<<< BLOCK END instance configure & startup stage 1
|
||||
|
||||
/** inner value: about why morny exit, used in [[daemon.MornyReport]]. */
|
||||
/** inner value: about why morny exit. */
|
||||
private var whileExit_reason: Option[AnyRef] = None
|
||||
/** About why morny exits. */
|
||||
def exitReason: Option[AnyRef] = whileExit_reason
|
||||
@ -295,7 +297,6 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
||||
| server responses:
|
||||
|${GsonBuilder().setPrettyPrinting().create.toJson(e.response).indent(4)}
|
||||
|""".stripMargin
|
||||
externalContext.consume[MornyReport](_.exception(e, "Failed get updates."))
|
||||
}
|
||||
|
||||
if (e.getCause != null) {
|
||||
@ -319,7 +320,9 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
||||
logger `error`
|
||||
s"""Failed get updates:
|
||||
|${e_other.toLogString `indent` 3}""".stripMargin
|
||||
externalContext.consume[MornyReport](_.exception(e_other, "Failed get updates."))
|
||||
|
||||
TelegramBotEvents.inCoeur.OnGetUpdateFailed.emit(e)
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -2,7 +2,7 @@ package cc.sukazyo.cono.morny.core.bot.api
|
||||
|
||||
import cc.sukazyo.cono.morny.core.{Log, MornyCoeur}
|
||||
import cc.sukazyo.cono.morny.core.Log.logger
|
||||
import cc.sukazyo.cono.morny.reporter.MornyReport
|
||||
import cc.sukazyo.cono.morny.core.event.TelegramBotEvents
|
||||
import cc.sukazyo.cono.morny.system.telegram_api.event.{EventEnv, EventListener, EventRuntimeException}
|
||||
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
|
||||
import com.google.gson.GsonBuilder
|
||||
@ -49,7 +49,7 @@ class EventListenerManager (using coeur: MornyCoeur) extends UpdatesListener {
|
||||
i.atEventPost
|
||||
}
|
||||
|
||||
private def runEventListener (i: EventListener)(using EventEnv): Unit = {
|
||||
private def runEventListener (i: EventListener)(using event: EventEnv): Unit = {
|
||||
try {
|
||||
i.on
|
||||
updateThreadName("message")
|
||||
@ -80,7 +80,7 @@ class EventListenerManager (using coeur: MornyCoeur) extends UpdatesListener {
|
||||
if update.chatMember ne null then i.onChatMemberUpdated
|
||||
updateThreadName("chat-join-request")
|
||||
if update.chatJoinRequest ne null then i.onChatJoinRequest
|
||||
} catch case e => {
|
||||
} catch case e: Throwable => {
|
||||
val errorMessage = StringBuilder()
|
||||
errorMessage ++= "Event throws unexpected exception:\n"
|
||||
errorMessage ++= (e.toLogString `indent` 4)
|
||||
@ -92,7 +92,7 @@ class EventListenerManager (using coeur: MornyCoeur) extends UpdatesListener {
|
||||
) `indent` 4) ++= "\n"
|
||||
case _ =>
|
||||
logger `error` errorMessage.toString
|
||||
coeur.externalContext.consume[MornyReport](_.exception(e, "on event running"))
|
||||
TelegramBotEvents.inCoeur.OnListenerOccursException.emit((e, i, event))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,41 @@
|
||||
package cc.sukazyo.cono.morny.core.event
|
||||
|
||||
import cc.sukazyo.cono.morny.core.MornyCoeur
|
||||
import cc.sukazyo.cono.morny.system.telegram_api.event.{EventEnv, EventListener as TelegramEventListener}
|
||||
import cc.sukazyo.std.event.{EventContext, RichEvent}
|
||||
import cc.sukazyo.std.event.impl.NormalEventManager
|
||||
import com.pengrad.telegrambot.TelegramException
|
||||
|
||||
class TelegramBotEvents (using coeur: MornyCoeur) {
|
||||
|
||||
private val contextInitializer: EventContext[?]=>Unit = context => {
|
||||
context.givenCxt << coeur
|
||||
}
|
||||
|
||||
/**
|
||||
* Event: OnGetUpdateFailed in TelegramBotEvents
|
||||
*
|
||||
* This event will be emitted when an exception occurred when the Telegram Bot is trying
|
||||
* to execute the GetUpdate.
|
||||
*
|
||||
* Provides a [[TelegramException]] that contains the exception information.
|
||||
*
|
||||
* Event is initialized after the [[MornyModule.onStarting]] stage, and before the
|
||||
* [[MornyModule.onStartingPost]] stage.
|
||||
* You should register your own listener at stage [[MornyModule.onStartingPost]].
|
||||
*/
|
||||
val OnGetUpdateFailed: NormalEventManager[TelegramException, Unit] =
|
||||
NormalEventManager().initContextWith(contextInitializer)
|
||||
|
||||
val OnListenerOccursException: RichEvent[(Throwable, TelegramEventListener, EventEnv), Unit] =
|
||||
NormalEventManager().initContextWith(contextInitializer)
|
||||
|
||||
}
|
||||
|
||||
object TelegramBotEvents {
|
||||
|
||||
def inCoeur (using coeur: MornyCoeur): TelegramBotEvents = in(coeur)
|
||||
def in (coeur: MornyCoeur): TelegramBotEvents =
|
||||
coeur.telegramBotEvents
|
||||
|
||||
}
|
@ -3,6 +3,7 @@ package cc.sukazyo.cono.morny.reporter
|
||||
import cc.sukazyo.cono.morny.core.internal.MornyInternalModule
|
||||
import cc.sukazyo.cono.morny.core.Log.logger
|
||||
import cc.sukazyo.cono.morny.core.MornyCoeur
|
||||
import cc.sukazyo.cono.morny.core.event.TelegramBotEvents
|
||||
|
||||
class Module extends MornyInternalModule {
|
||||
|
||||
@ -38,17 +39,27 @@ class Module extends MornyInternalModule {
|
||||
override def onStarting (using coeur: MornyCoeur)(cxt: MornyCoeur.OnStartingContext): Unit = {
|
||||
import coeur.externalContext
|
||||
externalContext >> { (instance: MornyReport) =>
|
||||
|
||||
instance.start()
|
||||
|
||||
TelegramBotEvents.inCoeur.OnGetUpdateFailed
|
||||
.registerListener(instance.botErrorsReport.onGetUpdateFailed)
|
||||
TelegramBotEvents.inCoeur.OnListenerOccursException
|
||||
.registerListener(instance.botErrorsReport.onEventListenersThrowException)
|
||||
|
||||
} || {
|
||||
logger `warn` "There seems no reporter instance is provided; skipped start it."
|
||||
}
|
||||
}
|
||||
|
||||
override def onStartingPost (using coeur: MornyCoeur)(cxt: MornyCoeur.OnStartingPostContext): Unit = {
|
||||
|
||||
import coeur.externalContext
|
||||
|
||||
externalContext >> { (instance: MornyReport) =>
|
||||
instance.reportCoeurMornyLogin()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override def onExiting (using coeur: MornyCoeur): Unit = {
|
||||
|
@ -3,6 +3,7 @@ package cc.sukazyo.cono.morny.reporter
|
||||
import cc.sukazyo.cono.morny.core.{MornyCoeur, MornyConfig}
|
||||
import cc.sukazyo.cono.morny.core.Log.logger
|
||||
import cc.sukazyo.cono.morny.data.MornyInformation.getVersionAllFullTagHTML
|
||||
import cc.sukazyo.cono.morny.reporter.telegram_bot.BotErrorsReport
|
||||
import cc.sukazyo.cono.morny.system.telegram_api.event.{EventEnv, EventListener, EventRuntimeException}
|
||||
import cc.sukazyo.cono.morny.system.telegram_api.formatting.TelegramFormatter.*
|
||||
import cc.sukazyo.cono.morny.system.telegram_api.formatting.TelegramParseEscape.escapeHtml as h
|
||||
@ -26,7 +27,9 @@ import com.pengrad.telegrambot.TelegramException
|
||||
|
||||
import java.time.ZoneId
|
||||
|
||||
class MornyReport (using coeur: MornyCoeur) {
|
||||
class MornyReport (using val coeur: MornyCoeur) {
|
||||
|
||||
given reporter: MornyReport = this
|
||||
|
||||
private val enabled = coeur.config.reportToChat != -1
|
||||
if !enabled then
|
||||
@ -146,6 +149,8 @@ class MornyReport (using coeur: MornyCoeur) {
|
||||
).parseMode(ParseMode HTML))
|
||||
}
|
||||
|
||||
object botErrorsReport extends BotErrorsReport()
|
||||
|
||||
object EventStatistics {
|
||||
|
||||
private var eventTotal = 0
|
||||
@ -280,3 +285,10 @@ class MornyReport (using coeur: MornyCoeur) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object MornyReport {
|
||||
|
||||
def inCoeur (coeur: MornyCoeur): MornyReport =
|
||||
coeur.externalContext.getUnsafe[MornyReport]
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package cc.sukazyo.cono.morny.reporter.telegram_bot
|
||||
|
||||
import cc.sukazyo.cono.morny.core.event.TelegramBotEvents
|
||||
import cc.sukazyo.cono.morny.reporter.MornyReport
|
||||
|
||||
class BotErrorsReport (using reporter: MornyReport) {
|
||||
|
||||
private val _TBotEvents = TelegramBotEvents.inCoeur(using reporter.coeur)
|
||||
|
||||
val onGetUpdateFailed: _TBotEvents.OnGetUpdateFailed.MyCallback
|
||||
= telegramException => {
|
||||
|
||||
if (telegramException.response != null) {
|
||||
// if the response exists, means connections to the server is successful, but
|
||||
// server can't process the request.
|
||||
// due to connections to the server is ok, the report should be able to send to
|
||||
// the telegram side.
|
||||
reporter.exception(telegramException, "Failed get updates.")
|
||||
}
|
||||
|
||||
if (telegramException.getCause != null) {
|
||||
import java.net.{SocketException, SocketTimeoutException}
|
||||
import javax.net.ssl.SSLHandshakeException
|
||||
val caused = telegramException.getCause
|
||||
caused match
|
||||
case _: (SSLHandshakeException|SocketException|SocketTimeoutException) =>
|
||||
case e_other =>
|
||||
reporter.exception(e_other, "Failed get updates.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val onEventListenersThrowException: _TBotEvents.OnListenerOccursException.MyCallback
|
||||
= (e, _, _) => {
|
||||
reporter.exception(e, "on event running")
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,12 @@ package cc.sukazyo.cono.morny.social_share.external
|
||||
|
||||
import scala.util.matching.Regex
|
||||
|
||||
/** Public twitter objects and utilities.
|
||||
*
|
||||
* Contains:
|
||||
* - Twitter's tweet url object [[TweetUrlInformation]], and its parser [[parseTweetUrl]] &
|
||||
* [[guessTweetUrl]].
|
||||
*/
|
||||
package object twitter {
|
||||
|
||||
private val REGEX_TWEET_URL: Regex = "(?:https?://)?((?:(?:(?:c\\.)?vx|fx|www\\.)?twitter|(?:www\\.|fixup|fixv)?x)\\.com)/((\\w+)/status/(\\d+)(?:/photo/(\\d+))?)/?(?:\\?(\\S+))?"r
|
||||
@ -69,6 +75,20 @@ package object twitter {
|
||||
))
|
||||
case _ => None
|
||||
|
||||
/** Find all the possible Twitter/X URL from the given text.
|
||||
*
|
||||
* It supports url like [[parseTweetUrl]] supports, the only difference is that this
|
||||
* method can find all the possible urls in the text using [[Regex.findAllMatchIn]],
|
||||
* instead of strictly match the text.
|
||||
*
|
||||
* For each Twitter URL found in the text, a corresponds [[TweetUrlInformation]] will be
|
||||
* created.
|
||||
*
|
||||
* @param text The text that may contain tweet url.
|
||||
* @return A list of [[TweetUrlInformation]].
|
||||
* Each twitter url found in the text corresponds to one [[TwitterUrlInformation]].
|
||||
* If no url is found, an empty list will be returned.
|
||||
*/
|
||||
def guessTweetUrl (text: String): List[TweetUrlInformation] =
|
||||
REGEX_TWEET_URL.findAllMatchIn(text).map(f => {
|
||||
TweetUrlInformation(
|
||||
|
@ -1,8 +1,8 @@
|
||||
package cc.sukazyo.cono.morny.system.telegram_api.event
|
||||
|
||||
import cc.sukazyo.cono.morny.system.utils.EpochDateTime.EpochMillis
|
||||
import cc.sukazyo.cono.morny.system.utils.GivenContext
|
||||
import cc.sukazyo.messiva.utils.StackUtils
|
||||
import cc.sukazyo.std.contexts.GivenContext
|
||||
import com.pengrad.telegrambot.model.Update
|
||||
|
||||
import scala.collection.mutable
|
||||
|
@ -1,156 +0,0 @@
|
||||
package cc.sukazyo.cono.morny.system.utils
|
||||
|
||||
import cc.sukazyo.cono.morny.system.utils.GivenContext.{ContextNotGivenException, FolderClass, RequestItemClass}
|
||||
|
||||
import scala.annotation.targetName
|
||||
import scala.collection.mutable
|
||||
import scala.reflect.{classTag, ClassTag}
|
||||
|
||||
object GivenContext {
|
||||
case class FolderClass (clazz: Option[Class[?]])
|
||||
object FolderClass:
|
||||
def default: FolderClass = FolderClass(None)
|
||||
case class RequestItemClass (clazz: Class[?])
|
||||
|
||||
class ContextNotGivenException (using
|
||||
val requestItemClass: RequestItemClass,
|
||||
val folderClass: FolderClass = FolderClass.default,
|
||||
val requestStack: StackTraceElement = UseStacks.getStackHeadBeforeClass[GivenContext]
|
||||
) extends NoSuchElementException (
|
||||
s"None of the ${requestItemClass.clazz.getSimpleName} is in the context${folderClass.clazz.map(" and owned by " + _.getSimpleName).getOrElse("")}, which is required by $requestStack."
|
||||
)
|
||||
}
|
||||
|
||||
/** A mutable collection that can store(provide) any typed value and read(use/consume) that value by type.
|
||||
*
|
||||
* @example {{{
|
||||
* val cxt = GivenContext()
|
||||
* class BaseClass {}
|
||||
* class MyImplementation extends BaseClass {}
|
||||
*
|
||||
*
|
||||
* cxt.provide(true) // this provides a Boolean
|
||||
* cxt.provide[BaseClass](new MyImplementation()) // although this object is of type MyImplementation, but it is stored
|
||||
* // as BaseClass so you can (and actually can only) read it using BaseClass
|
||||
* cxt << "string"
|
||||
* cxt << classOf[Int] -> 1 // you can also manually set the stored type using this method
|
||||
*
|
||||
*
|
||||
* cxt >> { (i: Int) => println(i) } || { println("no Int data in the context") }
|
||||
* val bool =
|
||||
* cxt.use[String, Boolean] { s => println(s); true } || { false } // when using .use, the return value must declared
|
||||
* cxt.consume[String] { s => println(s) } // you can use .consume if you don't care the return
|
||||
* // and this will return a cxt.ConsumeResult[Any]
|
||||
* val cxtResultOpt = // use toOption if you do not want fallback calculation
|
||||
* cxt.use[Int, String](int => s"int: $int").toOption // this returns Option[String]
|
||||
* val cxtResultOpt2 =
|
||||
* cxt >> { (int: Int) => s"int: $int" } |? // this returns Option[String] too
|
||||
* // cxt >> { (int: Int) => cxt >> { (str: String) => { str + int } } } |? // this below is not good to use due to .flatUse
|
||||
* // is not supported yet. It will return a
|
||||
* // cxt.ConsumeResult[Option[String]] which is very bad
|
||||
*
|
||||
* try { // for now, you can use this way to use multiple data
|
||||
* val int = cxt.use[Int] // this returns CxtOption[Int] which is Either[ContextNotGivenException, Int]
|
||||
* .toTry.get
|
||||
* val str = cxt >> classOf[String] match // this >> returns the same with the .use above
|
||||
* case Right(s) => s
|
||||
* case Left(err) => throw err // this is ContextNotGivenException
|
||||
* val bool = cxt >!> classOf[Boolean] // the easier way to do the above
|
||||
* } catch case e: ContextNotGivenException => // if any of the above val is not available, it will catch the exception
|
||||
* e.printStackTrace()
|
||||
* }}}
|
||||
*
|
||||
* TODO: Tests
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
//noinspection NoTargetNameAnnotationForOperatorLikeDefinition
|
||||
class GivenContext {
|
||||
|
||||
private type ImplicitsMap [T <: Any] = mutable.HashMap[Class[?], T]
|
||||
|
||||
private val variables: ImplicitsMap[Any] = mutable.HashMap.empty
|
||||
private val variablesWithOwner: ImplicitsMap[ImplicitsMap[Any]] = mutable.HashMap.empty
|
||||
|
||||
infix def provide [T: ClassTag] (i: T): Unit =
|
||||
variables += (classTag[T].runtimeClass -> i)
|
||||
def << [T: ClassTag] (is: (Class[T], T)): Unit =
|
||||
val (_, i) = is
|
||||
this.provide[T](i)
|
||||
def << [T: ClassTag] (i: T): Unit =
|
||||
this.provide[T](i)
|
||||
|
||||
private type CxtOption[T] = Either[ContextNotGivenException, T]
|
||||
def use [T: ClassTag]: CxtOption[T] =
|
||||
given t: RequestItemClass = RequestItemClass(classTag[T].runtimeClass)
|
||||
variables get t.clazz match
|
||||
case Some(i) => Right(i.asInstanceOf[T])
|
||||
case None => Left(ContextNotGivenException())
|
||||
infix def use [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||
this.use[T] match
|
||||
case Left(_) => ConsumeFailed[U]()
|
||||
case Right(i) => ConsumeSucceed[U](consumer(i))
|
||||
def >> [T: ClassTag] (t: Class[T]): CxtOption[T] =
|
||||
this.use[T]
|
||||
def >!> [T: ClassTag] (t: Class[T]): T =
|
||||
this.use[T].toTry.get
|
||||
def >>[T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||
this.use[T,U](consumer)
|
||||
infix def consume [T: ClassTag] (consume: T => Any): ConsumeResult[Any] =
|
||||
this.use[T,Any](consume)
|
||||
|
||||
@targetName("ownedBy")
|
||||
def / [O: ClassTag] (owner: O): OwnedContext[O] =
|
||||
OwnedContext[O]()
|
||||
def ownedBy [O: ClassTag]: OwnedContext[O] =
|
||||
OwnedContext[O]()
|
||||
|
||||
class OwnedContext [O: ClassTag] {
|
||||
|
||||
infix def provide [T: ClassTag] (i: T): Unit =
|
||||
(variablesWithOwner getOrElseUpdate (classTag[O].runtimeClass, mutable.HashMap.empty))
|
||||
.addOne(classTag[T].runtimeClass -> i)
|
||||
def << [T: ClassTag] (is: (Class[T], T)): Unit =
|
||||
val (_, i) = is
|
||||
this.provide[T](i)
|
||||
def << [T: ClassTag] (i: T): Unit =
|
||||
this.provide[T](i)
|
||||
|
||||
def use [T: ClassTag]: CxtOption[T] =
|
||||
given t: RequestItemClass = RequestItemClass(classTag[T].runtimeClass)
|
||||
given u: FolderClass = FolderClass(Some(classTag[O].runtimeClass))
|
||||
variablesWithOwner get u.clazz.get match
|
||||
case Some(varColl) => varColl get t.clazz match
|
||||
case Some(i) => Right(i.asInstanceOf[T])
|
||||
case None => Left(ContextNotGivenException())
|
||||
case None => Left(ContextNotGivenException())
|
||||
infix def use [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||
use[T] match
|
||||
case Left(_) => ConsumeFailed[U]()
|
||||
case Right(i) => ConsumeSucceed[U](consumer(i))
|
||||
def >> [T: ClassTag] (t: Class[T]): CxtOption[T] =
|
||||
this.use[T]
|
||||
def >!> [T: ClassTag] (t: Class[T]): T =
|
||||
this.use[T].toTry.get
|
||||
def >> [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||
this.use[T,U](consumer)
|
||||
infix def consume [T: ClassTag] (consume: T => Any): ConsumeResult[Any] =
|
||||
this.use[T,Any](consume)
|
||||
|
||||
}
|
||||
|
||||
trait ConsumeResult[U]:
|
||||
def toOption: Option[U]
|
||||
def |? : Option[U] = toOption
|
||||
@targetName("orElse")
|
||||
def || (processor: =>U): U
|
||||
private class ConsumeSucceed[U] (succeedValue: U) extends ConsumeResult[U]:
|
||||
override def toOption: Option[U] = Some(succeedValue)
|
||||
@targetName("orElse")
|
||||
override def || (processor: => U): U = succeedValue
|
||||
private class ConsumeFailed[U] extends ConsumeResult[U]:
|
||||
override def toOption: Option[U] = None
|
||||
@targetName("orElse")
|
||||
override def || (processor: => U): U = processor
|
||||
|
||||
}
|
@ -42,10 +42,11 @@ object MornyConfiguration {
|
||||
|
||||
override val dependencies = Seq(
|
||||
|
||||
"com.github.spotbugs" % "spotbugs-annotations" % "4.9.0" % Compile,
|
||||
"com.github.spotbugs" % "spotbugs-annotations" % "4.9.1" % Compile,
|
||||
|
||||
"cc.sukazyo" % "messiva" % "0.2.0",
|
||||
"cc.sukazyo" % "resource-tools" % "0.3.1",
|
||||
"cc.sukazyo" % "da4a" % "0.2.0-SNAPSHOT" changing(),
|
||||
|
||||
"com.github.pengrad" % "java-telegram-bot-api" % "6.2.0",
|
||||
|
||||
@ -88,10 +89,11 @@ object MornyConfiguration {
|
||||
|
||||
override val dependencies = Seq(
|
||||
|
||||
"com.github.spotbugs" % "spotbugs-annotations" % "4.9.0" % Compile,
|
||||
"com.github.spotbugs" % "spotbugs-annotations" % "4.9.1" % Compile,
|
||||
|
||||
"cc.sukazyo" % "messiva" % "0.2.0",
|
||||
"cc.sukazyo" % "resource-tools" % "0.3.1",
|
||||
"cc.sukazyo" % "da4a" % "0.2.0-SNAPSHOT" changing(),
|
||||
|
||||
"com.github.pengrad" % "java-telegram-bot-api" % "6.2.0",
|
||||
"org.http4s" %% "http4s-dsl" % "0.23.30",
|
||||
|
Loading…
Reference in New Issue
Block a user