add file-based module loader and update resource-tools to 0.3.0

This commit is contained in:
A.C.Sukazyo Eyre 2024-07-03 14:50:33 +08:00
parent 11542377d5
commit 388351593a
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
27 changed files with 141 additions and 62 deletions

View File

@ -19,7 +19,7 @@ object MornyConfiguration {
"com.github.spotbugs" % "spotbugs-annotations" % "4.8.4" % Compile,
"cc.sukazyo" % "messiva" % "0.2.0",
"cc.sukazyo" % "resource-tools" % "0.2.2",
"cc.sukazyo" % "resource-tools" % "0.3.0",
"com.github.pengrad" % "java-telegram-bot-api" % "6.2.0",
"org.http4s" %% "http4s-dsl" % "0.23.27",

View File

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 286 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1,14 @@
cc.sukazyo.cono.morny.tele_utils.ModuleTeleUtils
cc.sukazyo.cono.morny.randomize_somthing.ModuleRandomize
cc.sukazyo.cono.morny.slash_action.ModuleSlashAction
cc.sukazyo.cono.morny.nbnhhsh.ModuleNbnhhsh
cc.sukazyo.cono.morny.ip186.ModuleIP186
cc.sukazyo.cono.morny.crons.ModuleCRONs
cc.sukazyo.cono.morny.encrypt_tool.ModuleEncryptor
cc.sukazyo.cono.morny.call_me.ModuleCallMe
cc.sukazyo.cono.morny.social_share.ModuleSocialShare
cc.sukazyo.cono.morny.medication_timer.ModuleMedicationTimer
cc.sukazyo.cono.morny.morny_misc.ModuleMornyMisc
cc.sukazyo.cono.morny.uni_meow.ModuleUniMeow
cc.sukazyo.cono.morny.reporter.Module
cc.sukazyo.cono.morny.stickers_get.Module

View File

@ -7,7 +7,7 @@ import java.io.IOException
object MornyAbout {
val MORNY_PREVIEW_IMAGE_ASCII: String =
try { MornyAssets.pack `getResource` "texts/server-hello.txt" readAsString }
try { MornyAssets.assets.getFile("texts/server-hello.txt").readString }
catch case e: IOException =>
throw RuntimeException("Cannot read MORNY_PREVIEW_IMAGE_ASCII from assets pack", e)

View File

@ -8,6 +8,7 @@ import cc.sukazyo.cono.morny.core.bot.event.{MornyOnInlineQuery, MornyOnTelegram
import cc.sukazyo.cono.morny.core.bot.internal.{ErrorMessageManager, ThreadingManagerImpl}
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.util.schedule.Scheduler
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
@ -15,6 +16,7 @@ import cc.sukazyo.cono.morny.util.time.WatchDog
import cc.sukazyo.cono.morny.util.GivenContext
import cc.sukazyo.cono.morny.util.UseString.MString
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
import cc.sukazyo.cono.morny.util.dataview.Table
import com.pengrad.telegrambot.TelegramBot
import com.pengrad.telegrambot.request.GetMe
@ -118,13 +120,9 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
given MornyCoeur = this
val externalContext: GivenContext = GivenContext()
import cc.sukazyo.cono.morny.util.dataview.Table.format as fmtTable
logger `info`
m"""The following Modules have been added to current Morny:
|${fmtTable(
"Module ID" :: "Module Name" :: "Module Version" :: Nil,
modules.map(f => f.id :: f.name :: f.version :: Nil)*
)}
|${ModuleHelper.drawTable(modules)}
|"""
///>>> BLOCK START local storage / data configuration

View File

@ -22,8 +22,8 @@ object MornyLangs {
val (lang_dir, lang_index_content) = try {
(
MornyAssets.pack.getResDir("langs"),
MornyAssets.pack.getResource("langs/_index.hyl").readAsString()
MornyAssets.assets.getDirectory("langs"),
MornyAssets.assets.getFile("langs/_index.hyl").readString
)
} catch case e: IOException =>
throw Exception("Cannot read Morny's translations file.", e)
@ -37,11 +37,10 @@ object MornyLangs {
val language_translations = mutable.HashMap.empty[String, Definitions]
for (file <- lang_dir.listFiles().filter(_.isFile)) yield {
for (file <- lang_dir.listFiles()) yield {
boundary {
import file.getPath as raw_path
if !(raw_path.endsWith(".hyt") || raw_path.endsWith(".hytrans")) then break()
val file_name = file.getPath.reverse.takeWhile(c => (c != '/') && (c != '\\')).reverse
val file_name = file.getPath.last
if !(file_name.endsWith(".hyt") || file_name.endsWith(".hytrans")) then break()
val file_basename = file_name.dropRight(
if file_name.endsWith(".hyt") then ".hyt".length
else ".hytrans".length
@ -51,7 +50,7 @@ object MornyLangs {
logger `warn` s"translation file \"$file_name\" is not in language index, so it got ignored (normalized lang name is \"$normalized\")."
break()
val lang_def = try {
val content = file.readAsString()
val content = file.readString
Parser.parse(content)
} catch case e: IOException =>
logger `error`

View File

@ -1,7 +1,8 @@
package cc.sukazyo.cono.morny.core
import cc.sukazyo.cono.morny.core.Log.logger
import cc.sukazyo.cono.morny.core.MornyConfig.CheckFailure
import cc.sukazyo.cono.morny.core.MornyConfig.{CheckFailure, PROP_TOKEN_KEY}
import cc.sukazyo.cono.morny.core.module.{ModuleHelper, ModuleLoader}
import cc.sukazyo.cono.morny.util.CommonFormat
import java.time.ZoneOffset
@ -19,6 +20,7 @@ object ServerMain {
val config = new MornyConfig.Prototype()
var mode_echoVersion = false
var mode_echoModules = false
var mode_echoHello = false
var mode_testRun = false
var showHello = true
@ -45,6 +47,7 @@ object ServerMain {
case "--no-hello" | "-hf" | "--quiet" | "-q" => showHello = false
case "--only-hello" | "-ho" | "-o" | "-hi" => mode_echoHello = true
case "--version" | "-v" => mode_echoVersion = true
case "--modules" | "-mod" => mode_echoModules = true
// deprecated: use --outdated-ignore instead
// case "--outdated-block" | "-ob" =>
@ -167,6 +170,8 @@ object ServerMain {
s"""The Skip Login feature is not implemented yet!
|""".stripMargin
val loadedModules = ModuleLoader.loadCoreModules()
if (mode_echoVersion) {
logger `info`
@ -195,10 +200,18 @@ object ServerMain {
| ${MornySystem.CODE_TIMESTAMP}
| ${CommonFormat.formatDate(MornySystem.CODE_TIMESTAMP, 0)} [UTC]"""
.stripMargin
return
}
if (mode_echoModules) {
logger `info` s"Loaded modules ::: \n${ModuleHelper.drawTable(loadedModules)}"
}
if mode_echoVersion | mode_echoModules then
return
logger `info`
s"""ServerMain.java Loaded >>>
|- version ${MornySystem.VERSION_FULL}
@ -222,7 +235,7 @@ object ServerMain {
try
MornyCoeur(
ServerModulesLoader.load()
loadedModules
)(using config build)(
testRun = mode_testRun
)

View File

@ -1,30 +0,0 @@
package cc.sukazyo.cono.morny.core
import cc.sukazyo.cono.morny
object ServerModulesLoader {
def load (): List[MornyModule] = {
List(
morny.tele_utils.ModuleTeleUtils(),
morny.randomize_somthing.ModuleRandomize(),
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(),
morny.medication_timer.ModuleMedicationTimer(),
morny.morny_misc.ModuleMornyMisc(),
morny.uni_meow.ModuleUniMeow(),
morny.reporter.Module(),
morny.stickers_get.Module(),
)
}
}

View File

@ -0,0 +1,15 @@
package cc.sukazyo.cono.morny.core.module
import cc.sukazyo.cono.morny.core.MornyModule
import cc.sukazyo.cono.morny.util.dataview.Table
object ModuleHelper {
def drawTable (modules: List[MornyModule]): String = {
Table.format(
"Module ID" :: "Module Name" :: "Module Version" :: Nil,
modules.map(f => f.id :: f.name :: f.version :: Nil) *
)
}
}

View File

@ -0,0 +1,51 @@
package cc.sukazyo.cono.morny.core.module
import cc.sukazyo.cono.morny.core.{MornyCoeur, MornyModule}
import cc.sukazyo.cono.morny.core.Log.logger
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
import java.nio.charset.StandardCharsets
import scala.collection.mutable.ListBuffer
object ModuleLoader {
def loadCoreModules (): List[MornyModule] = {
loadFromJar(classOf[MornyCoeur])
}
def loadFromJar (packageClazz: Class[?]): List[MornyModule] = {
val list = ListBuffer[MornyModule]()
val moduleListFile = packageClazz.getResourceAsStream("/morny-modules.list")
.readAllBytes()
val modules = String(moduleListFile, StandardCharsets.UTF_8)
.split("\n")
.map(_.strip)
.filter(_.nonEmpty)
modules.foreach { (clazzName: String) =>
try {
val clazz = Class.forName(clazzName)
val instance = clazz.getConstructor().newInstance()
instance match
case module: MornyModule =>
list += module
case _ =>
logger `error`
s"""Module is not a Morny Module :
| - in package : ${packageClazz.getName}
| - declared class name : $clazzName
|You need to implement a MornyModule trait to make it a REAL morny module!""".stripMargin
} catch case e: Exception =>
logger `error`
s"""Failed to create a module instance :
| - in package : ${packageClazz.getName}
| - declared class name : $clazzName
|${e.toLogString}
|Is this a typo or packaging error? You need to add morny-modules.list and your code to the same jar.""".stripMargin
}
list.toList
}
}

View File

@ -0,0 +1,9 @@
package cc.sukazyo.cono.morny.core.module
object ModulesJarLoader {
def load (): Unit = {
// TODO
}
}

View File

@ -1,11 +1,14 @@
package cc.sukazyo.cono.morny.data
import cc.sukazyo.restools.ResourcesPackage
import cc.sukazyo.restools.{ResourceDirectory, ResourcePackage}
object MornyAssets {
class AssetsException (caused: Throwable) extends Exception("Cannot read assets file.", caused)
val pack: ResourcesPackage = ResourcesPackage(MornyAssets.getClass, "assets_morny")
val assetsLocation: List[String] = "assets" :: "morny-coeur" :: Nil
val pack: ResourcePackage = ResourcePackage.get(assetsLocation :+ "morny-coeur.identifier" *)
val assets: ResourceDirectory = pack.getDirectory(assetsLocation*)
}

View File

@ -37,7 +37,7 @@ object MornyInformation {
catch case _: UnknownHostException => None
}
def getAboutPic: Array[Byte] = TelegramImages.IMG_ABOUT get
def getAboutPic: Array[Byte] = TelegramImages.IMG_ABOUT.get
def getMornyAboutLinksVars: List[Var] =
List(

View File

@ -8,7 +8,7 @@ import scala.util.Using
object TelegramImages {
class AssetsFileImage (assetsPath: String) {
class AssetsFileImage (assetsPath: List[String]) {
private var cache: Option[Array[Byte]] = None
@ -19,7 +19,7 @@ object TelegramImages {
@throws[AssetsException]
private def read (): Unit = {
Using ((MornyAssets.pack `getResource` assetsPath)read) { stream =>
Using (MornyAssets.assets.getFile(assetsPath*).read()) { stream =>
try { this.cache = Some(stream.readAllBytes()) }
catch case e: IOException => {
throw AssetsException(e)
@ -29,11 +29,18 @@ object TelegramImages {
}
val IMG_ABOUT: AssetsFileImage = AssetsFileImage("images/featured-image@0.5x.jpg")
val IMG_400: AssetsFileImage = AssetsFileImage("images/http-sekai-400.png")
val IMG_404: AssetsFileImage = AssetsFileImage("images/http-sekai-404.png")
val IMG_500: AssetsFileImage = AssetsFileImage("images/http-sekai-500.png")
val IMG_501: AssetsFileImage = AssetsFileImage("images/http-sekai-501.png")
val IMG_523: AssetsFileImage = AssetsFileImage("images/http-sekai-523.png")
object AssetsFileImage {
def byId (id: String): AssetsFileImage =
byId(id, "png")
def byId (id: String, ty: String): AssetsFileImage =
AssetsFileImage("images" :: s"$id.$ty" :: Nil);
}
val IMG_ABOUT: AssetsFileImage = AssetsFileImage.byId("featured-image@0.5x", "jpg")
val IMG_400: AssetsFileImage = AssetsFileImage.byId("http-sekai-400")
val IMG_404: AssetsFileImage = AssetsFileImage.byId("http-sekai-404")
val IMG_500: AssetsFileImage = AssetsFileImage.byId("http-sekai-500")
val IMG_501: AssetsFileImage = AssetsFileImage.byId("http-sekai-501")
val IMG_523: AssetsFileImage = AssetsFileImage.byId("http-sekai-523")
}

View File

@ -1,13 +1,13 @@
package cc.sukazyo.cono.morny.test
import cc.sukazyo.restools.ResourcesPackage
import cc.sukazyo.restools.{ResourceDirectory, ResourcePackage}
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.should
abstract class MornyTests extends AnyFreeSpec with should.Matchers {
val assets: ResourcesPackage =
ResourcesPackage(classOf[MornyTests], "assets_morny_tests")
val pack: ResourcePackage = ResourcePackage.get("assets_morny_tests")
val assets: ResourceDirectory = pack.getDirectory("assets_morny_tests")
val pending_val = "[not-implemented]"

View File

@ -83,7 +83,7 @@ class CommonEncryptTest extends MornyTests with TableDrivenPropertyChecks {
if file == null then
Array.empty[Byte]
else
assets.getResource(file).read.readAllBytes
assets.getFile(file).read.readAllBytes
s"while hashing binary $_name :" - {