Compare commits

...

2 Commits

75 changed files with 551 additions and 220 deletions

View File

@ -37,6 +37,9 @@ object MornyCoeur {
userid: Long,
tasks: Scheduler,
trusted: MornyTrusted,
eventManager: EventListenerManager,
commandManager: MornyCommandManager,
queryManager: MornyQueryManager,
givenCxt: GivenContext
)
@ -153,19 +156,45 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
/** current Morny's [[MornyTrusted]] instance */
val trusted: MornyTrusted = MornyTrusted()
modules.foreach(it => it.onInitializingPre(OnInitializingPreContext(
externalContext,
coeurStartTimestamp, account, username, userid, tasks, trusted,
initializeContext)))
val daemons: MornyDaemons = MornyDaemons()
initializeContext << daemons
val eventManager: EventListenerManager = EventListenerManager()
eventManager register MornyOnUpdateTimestampOffsetLock()
val commands: MornyCommandManager = MornyCommandManager()
val queries: MornyQueryManager = MornyQueryManager()
// Coeur Initializing Pre Event
modules.foreach(it => it.onInitializingPre(OnInitializingPreContext(
externalContext,
coeurStartTimestamp, account, username, userid, tasks, trusted,
eventManager, commands, queries,
initializeContext)))
// register core/api events
eventManager register MornyOnUpdateTimestampOffsetLock()
eventManager register MornyOnTelegramCommand(using commands)
eventManager register MornyOnInlineQuery(using queries)
{ // register core commands
import bot.command.*
val $MornyHellos = MornyHellos()
val $MornyInformation = MornyInformation()
val $MornyInformationOlds = MornyInformationOlds(using $MornyInformation)
val $MornyManagers = MornyManagers()
commands.register(
$MornyHellos.On,
$MornyHellos.Hello,
MornyInfoOnStart(),
$MornyManagers.SaveData,
$MornyInformation,
$MornyInformationOlds.Version,
$MornyInformationOlds.Runtime,
$MornyManagers.Exit,
DirectMsgClear(),
)
}
// Coeur Initializing Event
modules.foreach(it => it.onInitializing(OnInitializingContext(
@ -175,7 +204,6 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
initializeContext)))
eventManager register daemons.reporter.EventStatistics.EventInfoCatcher
val watchDog: WatchDog = WatchDog("watch-dog", 1000, 1500, { (consumed, _) =>
import cc.sukazyo.cono.morny.util.CommonFormat.formatDuration as f
logger warn
@ -184,6 +212,8 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
tasks.notifyIt()
})
initializeContext / this << watchDog
// Coeur Initializing Post Event
modules.foreach(it => it.onInitializingPost(OnInitializingPostContext(
externalContext,
coeurStartTimestamp, account, username, userid, tasks, trusted,
@ -197,11 +227,13 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
logger info "done test run, exiting."
this.exit(0, TestRun)
// Coeur Starting Pre
configure_exitCleanup()
// put things that need to cleanup when exit below
// so that it will be correctly cleanup when normal run and will not execute in testRun.
// Coeur Starting Event
modules.foreach(it => it.onStarting(OnStartingContext(
initializeContext)))
daemons.start()
logger info "start telegram event listening"
import com.pengrad.telegrambot.TelegramException
@ -250,6 +282,8 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
}
})
// Coeur Starting Post Event
modules.foreach(it => it.onStartingPost(OnStartingPostContext(
initializeContext)))
@ -270,14 +304,15 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
private def exitCleanup (): Unit = {
daemons.reporter.reportCoeurExit()
modules.foreach(it => it.onExiting)
account.shutdown()
logger info "stopped bot account"
modules.foreach(it => it.onExit)
daemons.stop()
tasks.waitForStop()
logger info s"morny tasks stopped: remains ${tasks.amount} tasks not be executed"
if config.commandLogoutClear then
commands.automaticTGListRemove()
modules.foreach(it => it.onExited)
logger info "done exit cleanup"
}

View File

@ -1,84 +0,0 @@
package cc.sukazyo.cono.morny
import cc.sukazyo.cono.morny.MornyCoeur.OnInitializingContext
class MornyCoreModule extends MornyModule {
override val id: String = "cc.sukazyo.cono.morny.bot"
override val name: String = "Morny Coeur - Core (for refactor temporary)"
override val version: String = MornySystem.VERSION
override val description: String | Null =
"""Core module of Morny Coeur.
|
|Exists for temporary use, when refactor completed it should be replaced
|by all other small modules that provide different functionality.
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: OnInitializingContext): Unit = {
import cc.sukazyo.cono.morny.bot.command.*
import cc.sukazyo.cono.morny.bot.event.*
import cc.sukazyo.cono.morny.bot.query.*
import cxt.*
val $OnUserRandom = OnUserRandom()
eventManager.register(
// ACTIVITY_RECORDER
// KUOHUANHUAN_NEED_SLEEP
$OnUserRandom.RandomSelect,
//noinspection NonAsciiCharacters
$OnUserRandom.尊嘟假嘟,
OnQuestionMarkReply(),
OnUserSlashAction(),
OnCallMe(),
OnCallMsgSend(),
OnGetSocial(),
OnMedicationNotifyApply(),
OnEventHackHandle()
)
val $MornyHellos = MornyHellos()
val $IP186Query = IP186Query()
val $MornyInformation = MornyInformation()
val $MornyInformationOlds = MornyInformationOlds(using $MornyInformation)
val $MornyManagers = MornyManagers()
//noinspection NonAsciiCharacters
val $创 = ()
commandManager.register(
$MornyHellos.On,
$MornyHellos.Hello,
MornyInfoOnStart(),
GetUsernameAndId(),
EventHack(),
Nbnhhsh(),
$IP186Query.IP,
$IP186Query.Whois,
Encryptor(),
MornyOldJrrp(),
GetSocial(),
$MornyManagers.SaveData,
$MornyInformation,
$MornyInformationOlds.Version,
$MornyInformationOlds.Runtime,
$MornyManagers.Exit,
Testing(),
DirectMsgClear(),
//noinspection NonAsciiCharacters
$创.Chuang
)
queryManager.register(
RawText(),
MyInformation(),
ShareToolTwitter(),
ShareToolBilibili(),
ShareToolSocialContent()
)
}
}

View File

@ -19,6 +19,7 @@ trait MornyModule {
def onRoutineSavingData (using MornyCoeur): Unit = {}
def onExit (using MornyCoeur): Unit = {}
def onExiting (using MornyCoeur): Unit = {}
def onExited (using MornyCoeur): Unit = {}
}

View File

@ -0,0 +1,25 @@
package cc.sukazyo.cono.morny
object ServerModulesLoader {
def load (): List[MornyModule] = {
List(
tele_utils.ModuleTeleUtils(),
randomize_somthing.ModuleRandomize(),
slash_action.ModuleSlashAction(),
nbnhhsh.ModuleNbnhhsh(),
ip186.ModuleIP186(),
encrypt_tool.ModuleEncryptor(),
call_me.ModuleCallMe(),
social_share.ModuleSocialShare(),
medication_timer.ModuleMedicationTimer(),
morny_misc.ModuleMornyMisc(),
uni_meow.ModuleUniMeow()
)
}
}

View File

@ -25,13 +25,6 @@ class MornyCommandManager (using coeur: MornyCoeur) {
for (alias <- i.aliases)
this.commands += (alias.name -> i)
private[bot] val commands_uni: CommandMap = mutable.SeqMap.empty
def registerForUni [T <: ISimpleCommand] (commands: T*): Unit =
for (i <- commands)
this.commands_uni += (i.name -> i)
for (alias <- i.aliases)
this.commands_uni += (alias.name -> i)
def execute (using command: InputCommand, event: Update): Boolean = {
if (commands contains command.command)
commands(command.command) execute;

View File

@ -0,0 +1,22 @@
package cc.sukazyo.cono.morny.call_me
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleCallMe extends MornyInternalModule {
override val id: String = "morny.call_me"
override val name: String = "Morny Can Call Master"
override val description: String | Null =
"""Provides a serial private message handler that can talk with Morny's Master
|inside the Morny bot PM.""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
eventManager register OnCallMe()
eventManager register OnCallMsgSend()
}
}

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.call_me
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}

View File

@ -1,10 +1,10 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.call_me
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.model.{Chat, Message, MessageEntity, Update}
import com.pengrad.telegrambot.model.{Chat, Message, MessageEntity}
import com.pengrad.telegrambot.model.request.ParseMode
import com.pengrad.telegrambot.request.{GetChat, SendMessage, SendSticker}

View File

@ -5,15 +5,12 @@ import cc.sukazyo.cono.morny.MornyCoeur
class MornyDaemons (using val coeur: MornyCoeur) {
val medicationTimer: MedicationTimer = MedicationTimer()
val reporter: MornyReport = MornyReport()
val eventHack: EventHacker = EventHacker()
def start (): Unit = {
logger notice "ALL Morny Daemons starting..."
medicationTimer.start()
reporter.start()
logger notice "Morny Daemons started."
@ -24,7 +21,6 @@ class MornyDaemons (using val coeur: MornyCoeur) {
logger notice "stopping All Morny Daemons..."
medicationTimer.stop()
reporter.stop()
logger notice "stopped ALL Morny Daemons."

View File

@ -1,7 +1,8 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.encrypt_tool
import cc.sukazyo.cono.morny.Log.logger
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.bot.command.ICommandAlias.ListedAlias
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.util.tgapi.InputCommand

View File

@ -0,0 +1,20 @@
package cc.sukazyo.cono.morny.encrypt_tool
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleEncryptor extends MornyInternalModule {
override val id: String = "morny.encrypt"
override val name: String = "Morny Encrypt Tools"
override val description: String | Null =
// language=markdown
"""Provides `/encrypt` command for enc/dec/hash things.
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
commandManager register Encryptor()
}
}

View File

@ -0,0 +1,9 @@
package cc.sukazyo.cono.morny.internal
import cc.sukazyo.cono.morny.{MornyModule, MornySystem}
trait MornyInternalModule extends MornyModule {
override val version: String = MornySystem.VERSION
}

View File

@ -1,7 +1,7 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.ip186
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.extra.ip186.IP186QueryHandler
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.model.Update
@ -10,7 +10,7 @@ import com.pengrad.telegrambot.request.SendMessage
import scala.language.postfixOps
class IP186Query (using coeur: MornyCoeur) {
class BotCommand (using coeur: MornyCoeur) {
private enum Subs (val cmd: String):
case IP extends Subs("ip")

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.ip186
package cc.sukazyo.cono.morny.ip186
import cc.sukazyo.cono.morny.util.SttpPublic.{mornyBasicRequest, Schemes}
import sttp.client3.{asString, HttpError, SttpClientException, UriContext}

View File

@ -1,3 +1,3 @@
package cc.sukazyo.cono.morny.extra.ip186
package cc.sukazyo.cono.morny.ip186
case class IP186Response (url: String, body: String)

View File

@ -0,0 +1,24 @@
package cc.sukazyo.cono.morny.ip186
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleIP186 extends MornyInternalModule {
override val id: String = "morny.ext.ip186"
override val name: String = "Morny ip.186 support"
override val description: String | Null =
// language=markdown
"""Provides `/ip` and `/markdown` commands, using ip.186516.xyz as query backend.
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
val $command = BotCommand()
commandManager.register(
$command.IP,
$command.Whois
)
}
}

View File

@ -1,8 +1,8 @@
package cc.sukazyo.cono.morny.daemon
package cc.sukazyo.cono.morny.medication_timer
import cc.sukazyo.cono.morny.Log.logger
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.daemon.MedicationTimer.calcNextRoutineTimestamp
import cc.sukazyo.cono.morny.medication_timer.MedicationTimer.calcNextRoutineTimestamp
import cc.sukazyo.cono.morny.util.schedule.RoutineTask
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import cc.sukazyo.cono.morny.util.CommonFormat

View File

@ -0,0 +1,57 @@
package cc.sukazyo.cono.morny.medication_timer
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.Log.logger
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleMedicationTimer extends MornyInternalModule {
override val id: String = "morny.medication_timer"
override val name: String = "Morny Medication Timer"
override val description: String | Null =
"""A notify tool for Morny notify its master to take medication.
|""".stripMargin
override def onInitializingPre (using MornyCoeur)(cxt: MornyCoeur.OnInitializingPreContext): Unit = {
import cxt.*
val instance: MedicationTimer = MedicationTimer()
externalContext << instance
givenCxt << instance
}
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
externalContext >> { (instance: MedicationTimer) =>
eventManager register OnMedicationNotifyApply(using instance)
} || {
logger warn "There seems no Medication Timer instance is provided; skipped register events for it."
}
}
override def onStarting (using coeur: MornyCoeur)(cxt: MornyCoeur.OnStartingContext): Unit = {
import coeur.*
externalContext >> { (instance: MedicationTimer) =>
instance.start()
} || {
logger warn "There seems no Medication Timer instance is provided; skipped start it."
}
}
override def onExiting (using coeur: MornyCoeur): Unit = {
import coeur.*
externalContext >> { (instance: MedicationTimer) =>
instance.stop()
} || {
logger warn "There seems no Medication Timer instance need to be stop."
}
}
}

View File

@ -1,10 +1,10 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.medication_timer
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}
import cc.sukazyo.cono.morny.MornyCoeur
import com.pengrad.telegrambot.model.Message
class OnMedicationNotifyApply (using coeur: MornyCoeur) extends EventListener {
class OnMedicationNotifyApply (using instance: MedicationTimer)(using coeur: MornyCoeur) extends EventListener {
override def onEditedMessage (using event: EventEnv): Unit =
editedMessageProcess(event.update.editedMessage)
@ -13,7 +13,7 @@ class OnMedicationNotifyApply (using coeur: MornyCoeur) extends EventListener {
private def editedMessageProcess (edited: Message)(using event: EventEnv): Unit = {
if edited.chat.id != coeur.config.medicationNotifyToChat then return;
if coeur.daemons.medicationTimer.refreshNotificationWrite(edited) then
if instance.refreshNotificationWrite(edited) then
event.setEventOk
}

View File

@ -0,0 +1,20 @@
package cc.sukazyo.cono.morny.morny_misc
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleMornyMisc extends MornyInternalModule {
override val id: String = "morny.misc"
override val name: String = "Morny Misc Things"
override val description: String | Null = "Misc things that from old days Morny."
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
commandManager register MornyOldJrrp()
commandManager register Testing()
}
}

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.data
package cc.sukazyo.cono.morny.morny_misc
import cc.sukazyo.cono.morny.util.EpochDateTime.{EpochDays, EpochMillis}
import com.pengrad.telegrambot.model.User

View File

@ -1,6 +1,7 @@
package cc.sukazyo.cono.morny.bot.command
import cc.sukazyo.cono.morny.data.MornyJrrp
package cc.sukazyo.cono.morny.morny_misc
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramFormatter.*
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec

View File

@ -1,6 +1,7 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.morny_misc
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ISimpleCommand}
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.model.Update

View File

@ -1,8 +1,8 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.nbnhhsh
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.extra.NbnhhshQuery
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.escapeHtml as h
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
@ -11,10 +11,9 @@ import com.pengrad.telegrambot.model.request.ParseMode
import com.pengrad.telegrambot.request.{SendMessage, SendSticker}
import sttp.client3.{HttpError, SttpClientException}
import java.io.IOException
import scala.language.postfixOps
class Nbnhhsh (using coeur: MornyCoeur) extends ITelegramCommand {
class CommandNbnhhsh (using coeur: MornyCoeur) extends ITelegramCommand {
private val NBNHHSH_RESULT_HEAD_HTML =
// language=html

View File

@ -0,0 +1,25 @@
package cc.sukazyo.cono.morny.nbnhhsh
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleNbnhhsh extends MornyInternalModule {
override val id: String = "morny.nbnhhsh"
override val name: String = "Morny Nbnhhsh Query"
override val description: String | Null =
// language=markdown
"""Provides a way to translate text using nbnhhsh(能不能好好说话) API.
|
|- command `/nbnhhsh` for translate input or replied.
|- inline query is still under WIP.
|
|API Url: https://lab.magiconch.com/api/nbnhhsh
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
commandManager register CommandNbnhhsh()
}
}

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra
package cc.sukazyo.cono.morny.nbnhhsh
import cc.sukazyo.cono.morny.util.SttpPublic.mornyBasicRequest
import com.google.gson.Gson

View File

@ -0,0 +1,29 @@
package cc.sukazyo.cono.morny.randomize_somthing
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleRandomize extends MornyInternalModule {
override val id: String = "morny.rand"
override val name: String = "Morny Randomize Something"
override val description: String | Null =
// language=markdown
"""Randomize reply something by rand.
|
|Can randomly reply like *尊嘟假嘟*, and provide support for */ $this or $that*,
|and more interesting things.
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
val $OnUserRandom = OnUserRandom()
eventManager register $OnUserRandom.RandomSelect
eventManager register OnQuestionMarkReply()
//noinspection NonAsciiCharacters
eventManager register $OnUserRandom.尊嘟假嘟
}
}

View File

@ -1,8 +1,8 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.randomize_somthing
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.event.OnQuestionMarkReply.isAllMessageMark
import cc.sukazyo.cono.morny.randomize_somthing.OnQuestionMarkReply.isAllMessageMark
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.request.SendMessage

View File

@ -1,9 +1,8 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.randomize_somthing
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.request.SendMessage
import com.pengrad.telegrambot.response.SendResponse
@ -13,7 +12,6 @@ class OnUserRandom (using coeur: MornyCoeur) {
object RandomSelect extends EventListener {
private val USER_OR_QUERY = "^(.+)(?:还是|or)(.+)$" r
private val USER_IF_QUERY = "^(.+)(?:吗\\?||\\?|吗?)$" r

View File

@ -0,0 +1,24 @@
package cc.sukazyo.cono.morny.slash_action
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleSlashAction extends MornyInternalModule {
override val id: String = "morny.slash"
override val name: String = "Morny SlashBot Support"
override val description: String | Null =
// language=markdown
"""Reply calls like "", "摸摸".
|
|This module requires *Group Privacy* set to `disabled` on the bot account.
|
|(@RongSlashBot)[https://t.me/RongSlashBot]
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
eventManager register OnUserSlashAction()
}
}

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.slash_action
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}

View File

@ -0,0 +1,28 @@
package cc.sukazyo.cono.morny.social_share
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
class ModuleSocialShare extends MornyInternalModule {
override val id: String = "morny.social"
override val name: String = "Morny Social Media Share Tools"
override val description: String | Null =
"""Provides a serial tools contains refactor share url, get content from
|social media, and more.
|""".stripMargin
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
queryManager register query.ShareToolTwitter()
queryManager register query.ShareToolBilibili()
commandManager register command.GetSocial()
eventManager register event.OnGetSocial()
queryManager register query.ShareToolSocialContent()
}
}

View File

@ -1,7 +1,7 @@
package cc.sukazyo.cono.morny.data.social
package cc.sukazyo.cono.morny.social_share.api
import cc.sukazyo.cono.morny.data.social.SocialContent.{SocialMedia, SocialMediaType, SocialMediaWithUrl}
import cc.sukazyo.cono.morny.data.social.SocialContent.SocialMediaType.{Photo, Video}
import cc.sukazyo.cono.morny.social_share.api.SocialContent.{SocialMedia, SocialMediaType, SocialMediaWithUrl}
import cc.sukazyo.cono.morny.social_share.api.SocialContent.SocialMediaType.{Photo, Video}
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.query.InlineQueryUnit
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec

View File

@ -1,8 +1,8 @@
package cc.sukazyo.cono.morny.data.social
package cc.sukazyo.cono.morny.social_share.api
import cc.sukazyo.cono.morny.data.social.SocialContent.{SocialMedia, SocialMediaWithUrl}
import cc.sukazyo.cono.morny.data.social.SocialContent.SocialMediaType.{Photo, Video}
import cc.sukazyo.cono.morny.extra.twitter.{FXApi, FXTweet}
import cc.sukazyo.cono.morny.social_share.api.SocialContent.{SocialMedia, SocialMediaWithUrl}
import cc.sukazyo.cono.morny.social_share.api.SocialContent.SocialMediaType.{Photo, Video}
import cc.sukazyo.cono.morny.social_share.external.twitter.{FXApi, FXTweet}
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.escapeHtml as h
object SocialTwitterParser {

View File

@ -1,8 +1,8 @@
package cc.sukazyo.cono.morny.data.social
package cc.sukazyo.cono.morny.social_share.api
import cc.sukazyo.cono.morny.data.social.SocialContent.SocialMediaType.Photo
import cc.sukazyo.cono.morny.data.social.SocialContent.SocialMediaWithBytesData
import cc.sukazyo.cono.morny.extra.weibo.{genWeiboStatusUrl, MApi, MStatus, StatusUrlInfo}
import cc.sukazyo.cono.morny.social_share.api.SocialContent.SocialMediaType.Photo
import cc.sukazyo.cono.morny.social_share.api.SocialContent.SocialMediaWithBytesData
import cc.sukazyo.cono.morny.social_share.external.weibo.{genWeiboStatusUrl, MApi, MStatus, StatusUrlInfo}
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.{cleanupHtml as ch, escapeHtml as h}
import io.circe.{DecodingFailure, ParsingFailure}
import sttp.client3.{HttpError, SttpClientException}

View File

@ -1,8 +1,10 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.social_share.command
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.event.OnGetSocial
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.social_share.event.OnGetSocial
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.request.SendSticker

View File

@ -1,13 +1,13 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.social_share.event
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}
import cc.sukazyo.cono.morny.bot.event.OnGetSocial.tryFetchSocial
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.extra.{twitter, weibo}
import cc.sukazyo.cono.morny.social_share.event.OnGetSocial.tryFetchSocial
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import cc.sukazyo.cono.morny.Log.{exceptionLog, logger}
import cc.sukazyo.cono.morny.data.social.{SocialTwitterParser, SocialWeiboParser}
import cc.sukazyo.cono.morny.social_share.api.{SocialTwitterParser, SocialWeiboParser}
import cc.sukazyo.cono.morny.social_share.external.{twitter, weibo}
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Message.entitiesSafe
import com.pengrad.telegrambot.model.Chat
import com.pengrad.telegrambot.model.request.ParseMode
@ -74,9 +74,9 @@ object OnGetSocial {
}
def tryFetchSocialOfTweet (url: twitter.TweetUrlInformation)(using replyChat: Long, replyToMessage: Int)(using coeur: MornyCoeur) =
import cc.sukazyo.cono.morny.social_share.external.twitter.FXApi
import io.circe.{DecodingFailure, ParsingFailure}
import sttp.client3.SttpClientException
import twitter.FXApi
try {
val api = FXApi.Fetch.status(Some(url.screenName), url.statusId)
SocialTwitterParser.parseFXTweet(api).outputToTelegram
@ -90,9 +90,9 @@ object OnGetSocial {
coeur.daemons.reporter.exception(e, "Error on requesting FixTweet API")
def tryFetchSocialOfWeibo (url: weibo.StatusUrlInfo)(using replyChat: Long, replyToMessage: Int)(using coeur: MornyCoeur) =
import cc.sukazyo.cono.morny.social_share.external.weibo.MApi
import io.circe.{DecodingFailure, ParsingFailure}
import sttp.client3.{HttpError, SttpClientException}
import weibo.MApi
try {
val api = MApi.Fetch.statuses_show(url.id)
SocialWeiboParser.parseMStatus(api).outputToTelegram

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.util
package cc.sukazyo.cono.morny.social_share.external.bilibili
import cc.sukazyo.cono.morny.util.UseMath.**

View File

@ -1,6 +1,5 @@
package cc.sukazyo.cono.morny.extra
package cc.sukazyo.cono.morny.social_share.external.bilibili
import cc.sukazyo.cono.morny.util.BiliTool
import cc.sukazyo.cono.morny.util.SttpPublic.{mornyBasicRequest, Schemes}
import cc.sukazyo.cono.morny.util.UseSelect.select
import sttp.client3.{HttpError, SttpClientException}

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
import cc.sukazyo.cono.morny.util.SttpPublic
import cc.sukazyo.cono.morny.util.SttpPublic.mornyBasicRequest

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** Information about the author of a tweet.
*

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** Data for external media, currently only video.
*

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
import cc.sukazyo.cono.morny.extra.twitter.FXMosaicPhoto.formatsType
import cc.sukazyo.cono.morny.social_share.external.twitter.FXMosaicPhoto.formatsType
/** Data for the mosaic service, which stitches photos together
*

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** This can help compare items in a pool of media
*

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** Data for a poll on a given Tweet.
*

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** Data for a single choice in a poll
*

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** Information about a requested translation for a Tweet, when asked.
*

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
import cc.sukazyo.cono.morny.extra.twitter.FXTweet.mediaType
import cc.sukazyo.cono.morny.social_share.external.twitter.FXTweet.mediaType
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochSeconds
/** The container of all the information for a Tweet.

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.twitter
package cc.sukazyo.cono.morny.social_share.external.twitter
/** Data for a Tweet's video
*

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra
package cc.sukazyo.cono.morny.social_share.external
import scala.util.matching.Regex

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.weibo
package cc.sukazyo.cono.morny.social_share.external.weibo
case class MApi [D] (
ok: Int,

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.weibo
package cc.sukazyo.cono.morny.social_share.external.weibo
case class MPic (
pid: String,

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.weibo
package cc.sukazyo.cono.morny.social_share.external.weibo
case class MStatus (

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra.weibo
package cc.sukazyo.cono.morny.social_share.external.weibo
case class MUser (

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.extra
package cc.sukazyo.cono.morny.social_share.external
package object weibo {

View File

@ -1,8 +1,9 @@
package cc.sukazyo.cono.morny.bot.query
package cc.sukazyo.cono.morny.social_share.query
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.util.tgapi.formatting.NamingUtils.inlineQueryId
import cc.sukazyo.cono.morny.Log.{exceptionLog, logger}
import cc.sukazyo.cono.morny.bot.query.{InlineQueryUnit, ITelegramQuery}
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.model.request.{InlineQueryResultArticle, InputTextMessageContent, ParseMode}
@ -24,7 +25,7 @@ class ShareToolBilibili (using coeur: MornyCoeur) extends ITelegramQuery {
if (event.inlineQuery.query == null) return null
if (event.inlineQuery.query isBlank) return null
import cc.sukazyo.cono.morny.extra.BilibiliForms.*
import cc.sukazyo.cono.morny.social_share.external.bilibili.BilibiliForms.*
val result: BiliVideoId =
try
parse_videoUrl(event.inlineQuery.query)

View File

@ -1,8 +1,10 @@
package cc.sukazyo.cono.morny.bot.query
import cc.sukazyo.cono.morny.data.social.{SocialTwitterParser, SocialWeiboParser}
import cc.sukazyo.cono.morny.extra.{twitter, weibo}
import cc.sukazyo.cono.morny.extra.twitter.{FXApi, TweetUrlInformation}
import cc.sukazyo.cono.morny.extra.weibo.{MApi, StatusUrlInfo}
package cc.sukazyo.cono.morny.social_share.query
import cc.sukazyo.cono.morny.bot.query.{InlineQueryUnit, ITelegramQuery}
import cc.sukazyo.cono.morny.social_share.api.{SocialTwitterParser, SocialWeiboParser}
import cc.sukazyo.cono.morny.social_share.external.{twitter, weibo}
import cc.sukazyo.cono.morny.social_share.external.twitter.{FXApi, TweetUrlInformation}
import cc.sukazyo.cono.morny.social_share.external.weibo.{MApi, StatusUrlInfo}
import com.pengrad.telegrambot.model.Update
class ShareToolSocialContent extends ITelegramQuery {

View File

@ -1,7 +1,8 @@
package cc.sukazyo.cono.morny.bot.query
package cc.sukazyo.cono.morny.social_share.query
import cc.sukazyo.cono.morny.extra.twitter
import cc.sukazyo.cono.morny.extra.twitter.TweetUrlInformation
import cc.sukazyo.cono.morny.bot.query.{InlineQueryUnit, ITelegramQuery}
import cc.sukazyo.cono.morny.social_share.external.twitter
import cc.sukazyo.cono.morny.social_share.external.twitter.TweetUrlInformation
import cc.sukazyo.cono.morny.util.tgapi.formatting.NamingUtils.inlineQueryId
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.model.request.InlineQueryResultArticle

View File

@ -1,11 +1,13 @@
package cc.sukazyo.cono.morny.bot.query
package cc.sukazyo.cono.morny.tele_utils
import cc.sukazyo.cono.morny.bot.query.{InlineQueryUnit, ITelegramQuery}
import cc.sukazyo.cono.morny.util.tgapi.formatting.NamingUtils.inlineQueryId
import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.model.request.{InlineQueryResultArticle, InputTextMessageContent}
import scala.language.postfixOps
class RawText extends ITelegramQuery {
class InlineRawText extends ITelegramQuery {
private val ID_PREFIX = "[morny/r/text]"
private val TITLE = "Raw Text"

View File

@ -0,0 +1,45 @@
package cc.sukazyo.cono.morny.tele_utils
import cc.sukazyo.cono.morny.internal.MornyInternalModule
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.tele_utils.event_hack.{CommandEventHack, EventHacker, HackerEventHandler}
import cc.sukazyo.cono.morny.tele_utils.user_info.{CommandGetUser, InlineMyInformation}
class ModuleTeleUtils extends MornyInternalModule {
override val id: String = "morny.tele_utils"
override val name: String = "Morny Tele Utils : EventHack, User data, and more"
override val description: String | Null =
// language=markdown
"""Added a serial tools for developing easier on Telegram.
|
|- `/event_hack`: Get the next event's raw serial data of you.
|- `/user`: Get user metadata for you or your roommate or by id.
| Also supported to get user's DC.
|""".stripMargin
override def onInitializingPre (using MornyCoeur)(cxt: MornyCoeur.OnInitializingPreContext): Unit = {
import cxt.*
given hacker: EventHacker = EventHacker()
externalContext << hacker
givenCxt << hacker
}
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
given EventHacker = externalContext >!> classOf[EventHacker]
eventManager register HackerEventHandler()
commandManager register CommandEventHack()
commandManager register CommandGetUser()
queryManager register InlineMyInformation()
queryManager register InlineRawText()
}
}

View File

@ -1,5 +1,7 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.tele_utils.event_hack
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.data.TelegramStickers
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
@ -8,7 +10,7 @@ import com.pengrad.telegrambot.request.SendSticker
import scala.language.postfixOps
class EventHack (using coeur: MornyCoeur) extends ITelegramCommand {
class CommandEventHack (using hacker: EventHacker)(using coeur: MornyCoeur) extends ITelegramCommand {
override val name: String = "event_hack"
override val aliases: List[ICommandAlias] = Nil
@ -17,7 +19,7 @@ class EventHack (using coeur: MornyCoeur) extends ITelegramCommand {
override def execute (using command: InputCommand, event: Update): Unit = {
import coeur.daemons.eventHack.{registerHack, HackType}
import hacker.{registerHack, HackType}
val x_mode = if (command.args nonEmpty) command.args(0) else ""

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.daemon
package cc.sukazyo.cono.morny.tele_utils.event_hack
import cc.sukazyo.cono.morny.Log.logger
import cc.sukazyo.cono.morny.MornyCoeur

View File

@ -1,4 +1,4 @@
package cc.sukazyo.cono.morny.bot.event
package cc.sukazyo.cono.morny.tele_utils.event_hack
import cc.sukazyo.cono.morny.bot.api.{EventEnv, EventListener}
import cc.sukazyo.cono.morny.Log.logger
@ -11,11 +11,11 @@ import com.pengrad.telegrambot.request.SendMessage
import scala.collection.mutable
import scala.language.postfixOps
class OnEventHackHandle (using coeur: MornyCoeur) extends EventListener {
class HackerEventHandler (using hacker: EventHacker)(using coeur: MornyCoeur) extends EventListener {
private def trigger (chat_id: Long, from_id: Long)(using event: EventEnv): Unit =
given Update = event.update
if coeur.daemons.eventHack.trigger(chat_id, from_id) then
if hacker.trigger(chat_id, from_id) then
event.setEventOk
override def onMessage (using event: EventEnv): Unit =

View File

@ -1,6 +1,7 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.tele_utils.user_info
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ITelegramCommand}
import cc.sukazyo.cono.morny.util.tgapi.{InputCommand, Standardize}
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramUserInformation
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
@ -10,7 +11,7 @@ import com.pengrad.telegrambot.request.{GetChatMember, SendMessage}
import scala.language.postfixOps
class GetUsernameAndId (using coeur: MornyCoeur) extends ITelegramCommand {
class CommandGetUser (using coeur: MornyCoeur) extends ITelegramCommand {
override val name: String = "user"
override val aliases: List[ICommandAlias] = Nil

View File

@ -1,5 +1,6 @@
package cc.sukazyo.cono.morny.bot.query
package cc.sukazyo.cono.morny.tele_utils.user_info
import cc.sukazyo.cono.morny.bot.query.{InlineQueryUnit, ITelegramQuery}
import cc.sukazyo.cono.morny.util.tgapi.formatting.NamingUtils.inlineQueryId
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramUserInformation
import com.pengrad.telegrambot.model.Update
@ -7,7 +8,7 @@ import com.pengrad.telegrambot.model.request.{InlineQueryResultArticle, InputTex
import scala.language.postfixOps
class MyInformation extends ITelegramQuery {
class InlineMyInformation extends ITelegramQuery {
private val ID_PREFIX = "[morny/info/me]"
private val TITLE = "My Account Information"

View File

@ -1,12 +1,12 @@
package cc.sukazyo.cono.morny.uni_meow
import cc.sukazyo.cono.morny.{MornyCoeur, MornyModule, MornySystem}
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.internal.MornyInternalModule
class ModuleUniMeow extends MornyModule {
class ModuleUniMeow extends MornyInternalModule {
override val id: String = "coeur.uni_meow"
override val name: String = "Coeur Uni-Meow Commands"
override val version: String = MornySystem.VERSION
override val description: String | Null =
// language=Markdown
"""Provides support for unicode command in Telegram. Also provided some
@ -16,11 +16,15 @@ class ModuleUniMeow extends MornyModule {
val uni_commands: UniMeowCommandManager = UniMeowCommandManager()
override def onInitializingPre (using MornyCoeur)(cxt: MornyCoeur.OnInitializingPreContext): Unit = {
import cxt.*
externalContext << uni_commands
givenCxt << uni_commands
}
override def onInitializing (using MornyCoeur)(cxt: MornyCoeur.OnInitializingContext): Unit = {
import cxt.*
externalContext << uni_commands
givenCxt << uni_commands
eventManager.register(
BotEventUniMeowTrigger(using uni_commands)
)
@ -37,7 +41,8 @@ class ModuleUniMeow extends MornyModule {
//noinspection NonAsciiCharacters
commandManager.register(
$喵呜.Progynova,
私わね()
私わね(),
().Chuang
)
}

View File

@ -1,6 +1,7 @@
package cc.sukazyo.cono.morny.bot.command
package cc.sukazyo.cono.morny.uni_meow
import cc.sukazyo.cono.morny.MornyCoeur
import cc.sukazyo.cono.morny.bot.command.{ICommandAlias, ISimpleCommand}
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.*
import com.pengrad.telegrambot.model.{MessageEntity, Update}

View File

@ -1,13 +1,33 @@
package cc.sukazyo.cono.morny.util
import cc.sukazyo.cono.morny.util.GivenContext.ContextNotGivenException
import cc.sukazyo.cono.morny.util.GivenContext.{ContextNotGivenException, FolderClass, RequestItemClass}
import cc.sukazyo.messiva.utils.StackUtils
import scala.annotation.targetName
import scala.collection.mutable
import scala.reflect.{classTag, ClassTag}
import scala.util.boundary
object GivenContext {
class ContextNotGivenException extends NoSuchElementException
case class FolderClass (clazz: Option[Class[?]])
object FolderClass:
def default: FolderClass = FolderClass(None)
case class RequestItemClass (clazz: Class[?])
private def lastNonGCStack: StackTraceElement =
boundary {
for (stack <- StackUtils.getStackTrace(0)) {
if (!stack.getClassName.startsWith(classOf[GivenContext].getName))
boundary break stack
}
StackTraceElement("unknown", "unknown", "unknown", -1)
}
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.
@ -67,7 +87,8 @@ class GivenContext {
private type CxtOption[T] = Either[ContextNotGivenException, T]
def use [T: ClassTag]: CxtOption[T] =
variables get classTag[T].runtimeClass match
given t: RequestItemClass = RequestItemClass(classTag[T].runtimeClass)
variables get t.clazz match
case Some(i) => Right(i.asInstanceOf[T])
case None => Left(ContextNotGivenException())
def use [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
@ -101,8 +122,12 @@ class GivenContext {
this.provide[T](i)
def use [T: ClassTag]: CxtOption[T] =
variablesWithOwner(classTag[O].runtimeClass) get classTag[T].runtimeClass match
case Some(i) => Right(i.asInstanceOf[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())
def use [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
use[T] match

View File

@ -0,0 +1,20 @@
package cc.sukazyo.cono.morny.util
import cc.sukazyo.messiva.utils.StackUtils
import scala.reflect.{classTag, ClassTag}
import scala.util.boundary
object UseStacks {
def getStackHeadBeforeClass[T: ClassTag]: StackTraceElement = {
boundary {
for (stack <- StackUtils.getStackTrace(1)) {
if (!stack.getClassName.startsWith(classTag[T].runtimeClass.getName))
boundary break stack
}
StackTraceElement("unknown", "unknown", "unknown", -1)
}
}
}

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.test.bot.event
import cc.sukazyo.cono.morny.bot.event.OnQuestionMarkReply
import cc.sukazyo.cono.morny.randomize_somthing.OnQuestionMarkReply
import cc.sukazyo.cono.morny.test.MornyTests
import org.scalatest.prop.TableDrivenPropertyChecks

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.test.daemon
import cc.sukazyo.cono.morny.daemon.MedicationTimer
import cc.sukazyo.cono.morny.medication_timer.MedicationTimer
import cc.sukazyo.cono.morny.test.MornyTests
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
import org.scalatest.prop.TableDrivenPropertyChecks

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.test.extra
import cc.sukazyo.cono.morny.extra.BilibiliForms.*
import cc.sukazyo.cono.morny.social_share.external.bilibili.BilibiliForms.*
import cc.sukazyo.cono.morny.test.MornyTests
import org.scalatest.prop.TableDrivenPropertyChecks

View File

@ -1,7 +1,7 @@
package cc.sukazyo.cono.morny.test.extra.twitter
import cc.sukazyo.cono.morny.extra.twitter.FXApi
import cc.sukazyo.cono.morny.extra.twitter.FXApi.Fetch
import cc.sukazyo.cono.morny.social_share.external.twitter.FXApi
import cc.sukazyo.cono.morny.social_share.external.twitter.FXApi.Fetch
import cc.sukazyo.cono.morny.test.MornyTests
import org.scalatest.prop.TableDrivenPropertyChecks
import org.scalatest.tagobjects.{Network, Slow}

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.test.extra.twitter
import cc.sukazyo.cono.morny.extra.twitter.{parseTweetUrl, TweetUrlInformation}
import cc.sukazyo.cono.morny.social_share.external.twitter.{parseTweetUrl, TweetUrlInformation}
import cc.sukazyo.cono.morny.test.MornyTests
class PackageTest extends MornyTests {

View File

@ -16,13 +16,13 @@ class BiliToolTest extends MornyTests with TableDrivenPropertyChecks {
)
forAll (examples) { (bv, av) => s"while using av$av/BV$bv :" - {
import cc.sukazyo.cono.morny.util.BiliTool.{toAv, toBv}
import cc.sukazyo.cono.morny.social_share.external.bilibili.BiliTool.{toAv, toBv}
"av to bv works" in { toBv(av) shouldEqual bv }
"bv to av works" in { toAv(bv) shouldEqual av }
}}
"BV with unsupported length :" - {
import cc.sukazyo.cono.morny.util.BiliTool.{toAv, IllegalFormatException}
import cc.sukazyo.cono.morny.social_share.external.bilibili.BiliTool.{toAv, IllegalFormatException}
val examples = Table(
"bv",
"12345",
@ -48,7 +48,7 @@ class BiliToolTest extends MornyTests with TableDrivenPropertyChecks {
("1mK4O1C7Bl", "l"),
("1--4O1C7Bl", "[symbols]")
)
import cc.sukazyo.cono.morny.util.BiliTool.{toAv, IllegalFormatException}
import cc.sukazyo.cono.morny.social_share.external.bilibili.BiliTool.{toAv, IllegalFormatException}
forAll(examples) { (bv, with_sp) =>
s"'$with_sp' should throws IllegalFormatException" in:
an [IllegalFormatException] should be thrownBy toAv(bv)
@ -58,7 +58,7 @@ class BiliToolTest extends MornyTests with TableDrivenPropertyChecks {
"av/bv converting should be reversible" in {
for (_ <- 1 to 20) {
val rand_av = Random.between(0, 999999999L)
import cc.sukazyo.cono.morny.util.BiliTool.{toAv, toBv}
import cc.sukazyo.cono.morny.social_share.external.bilibili.BiliTool.{toAv, toBv}
val my_bv = toBv(rand_av)
toAv(my_bv) shouldEqual rand_av
toBv(toAv(my_bv)) shouldEqual my_bv