mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-22 19:24:53 +08:00
usable translations and Coeur DSL
This commit is contained in:
parent
9ddfa6539d
commit
aad79b9726
@ -8,7 +8,7 @@ object MornyConfiguration {
|
|||||||
val MORNY_CODE_STORE = "https://github.com/Eyre-S/Coeur-Morny-Cono"
|
val MORNY_CODE_STORE = "https://github.com/Eyre-S/Coeur-Morny-Cono"
|
||||||
val MORNY_COMMIT_PATH = "https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s"
|
val MORNY_COMMIT_PATH = "https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s"
|
||||||
|
|
||||||
val VERSION = "2.0.0-alpha18"
|
val VERSION = "2.0.0-alpha19"
|
||||||
val VERSION_DELTA: Option[String] = None
|
val VERSION_DELTA: Option[String] = None
|
||||||
val CODENAME = "xinzheng"
|
val CODENAME = "xinzheng"
|
||||||
|
|
||||||
|
@ -4,11 +4,26 @@
|
|||||||
&encoding=utf8
|
&encoding=utf8
|
||||||
&indent=1
|
&indent=1
|
||||||
|
|
||||||
|
morny.information.about_links
|
||||||
|
| <a href='{MORNY_SOURCECODE_LINK}'>source code</a> | <a href='{MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK}'>backup</a>
|
||||||
|
| <a href='{MORNY_ISSUE_TRACKER_LINK}'>Feedback / issue tracker</a>
|
||||||
|
| <a href='{MORNY_USER_GUIDE_LINK}'>User's Guide / documentations</a>
|
||||||
|
|
||||||
morny.command.info.message.about
|
morny.command.info.message.about
|
||||||
| <b>Morny Cono</b>
|
| <b>Morny Cono</b>
|
||||||
| An assistant rat(micromys minutus) from Annie。
|
| An assistant rat(micromys minutus) from Annie。
|
||||||
| ————————————————
|
| ————————————————
|
||||||
| {about_links}
|
| {morny.information.about_links}
|
||||||
|
|
||||||
|
morny.command.info.sub_start.message
|
||||||
|
| Welcome you meet the <b>Morny Cono</b>,<i>an assistant rat from Annie</i>。
|
||||||
|
| Morny has a lot variety of features。
|
||||||
|
|
|
||||||
|
| ————————————————
|
||||||
|
| {morny.information.about_links}
|
||||||
|
| ————————————————
|
||||||
|
|
|
||||||
|
| (You can use /info command to get these message in any time)
|
||||||
|
|
||||||
morny.command.info.version
|
morny.command.info.version
|
||||||
| version:
|
| version:
|
||||||
@ -50,4 +65,4 @@ morny.command.info.message.tasks
|
|||||||
morny.command.info.message.event
|
morny.command.info.message.event
|
||||||
| <b>Event Statistics :</b>
|
| <b>Event Statistics :</b>
|
||||||
| in today
|
| in today
|
||||||
| {event_statistics}""".stripMargin
|
| {event_statistics}
|
||||||
|
@ -4,8 +4,40 @@
|
|||||||
&encoding=utf8
|
&encoding=utf8
|
||||||
&indent=1
|
&indent=1
|
||||||
|
|
||||||
morny.command.info.about
|
morny.information.about_links
|
||||||
|
| <a href='{MORNY_SOURCECODE_LINK}'>source code</a> | <a href='{MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK}'>backup</a>
|
||||||
|
| <a href='{MORNY_ISSUE_TRACKER_LINK}'>反馈 / issue tracker</a>
|
||||||
|
| <a href='{MORNY_USER_GUIDE_LINK}'>使用说明书 / user guide & docs</a>
|
||||||
|
|
||||||
|
morny.command.info.message.about
|
||||||
| <b>Morny Cono</b>
|
| <b>Morny Cono</b>
|
||||||
| 来自安妮的侍从小鼠。
|
| 来自安妮的侍从小鼠。
|
||||||
| ————————————————
|
| ————————————————
|
||||||
| {about_links}
|
| {morny.information.about_links}
|
||||||
|
|
||||||
|
morny.command.info.sub_start.message
|
||||||
|
| 欢迎使用 <b>Morny Cono</b>,<i>来自安妮的侍从小鼠</i>。
|
||||||
|
| Morny 具有各种各样的功能。
|
||||||
|
|
|
||||||
|
| ————————————————
|
||||||
|
| {morny.information.about_links}
|
||||||
|
| ————————————————
|
||||||
|
|
|
||||||
|
| (你可以随时通过 /info 重新获得这些信息)
|
||||||
|
|
||||||
|
morny.misc.command_test.message
|
||||||
|
| <b>这只是一个 /test 测试命令。</b>测试 <i>id</i> 为 <code>1</code>。
|
||||||
|
| 你可以回复一条消息来测试回复消息的功能。
|
||||||
|
|
||||||
|
morny.misc.command_test.branch_normal.message
|
||||||
|
| 你完成了一个回复消息的测试!
|
||||||
|
| 你所回复的消息为:
|
||||||
|
|
|
||||||
|
| {replied_message}
|
||||||
|
|
||||||
|
morny.misc.command_test.branch_oops.err_message_simple
|
||||||
|
| 将会生成一条错误! (使用 <b>/inspect</b> 命令来洞察错误详细信息)
|
||||||
|
|
||||||
|
morny.misc.command_test.branch_oops.err_message_complex
|
||||||
|
| Oops: There is just a test error.
|
||||||
|
| 这个错误是由 <b>/test</b> 命令手动触发的,为了测试错误洞察命令是否可以正常工作。
|
||||||
|
16
src/main/resources/assets_morny/langs/zh_tw.hyt
Normal file
16
src/main/resources/assets_morny/langs/zh_tw.hyt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Morny Translations File
|
||||||
|
|
||||||
|
%1.0
|
||||||
|
&encoding=utf8
|
||||||
|
&indent=1
|
||||||
|
|
||||||
|
morny.information.about_links
|
||||||
|
| <a href='{MORNY_SOURCECODE_LINK}'>source code</a> | <a href='{MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK}'>backup</a>
|
||||||
|
| <a href='{MORNY_ISSUE_TRACKER_LINK}'>回饋 / issue tracker</a>
|
||||||
|
| <a href='{MORNY_USER_GUIDE_LINK}'>使用說明書 / user guide & docs</a>
|
||||||
|
|
||||||
|
morny.command.info.message.about
|
||||||
|
| <b>Morny Cono</b>
|
||||||
|
| 來自安妮的侍從小鼠。
|
||||||
|
| ————————————————
|
||||||
|
| {morny.information.about_links}
|
@ -2,7 +2,7 @@ package cc.sukazyo.cono.morny.core
|
|||||||
|
|
||||||
import cc.sukazyo.cono.morny.core.Log.logger
|
import cc.sukazyo.cono.morny.core.Log.logger
|
||||||
import cc.sukazyo.cono.morny.core.MornyCoeur.*
|
import cc.sukazyo.cono.morny.core.MornyCoeur.*
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.{EventListenerManager, MornyCommandManager, MornyQueryManager}
|
import cc.sukazyo.cono.morny.core.bot.api.{BotExtension, EventListenerManager, MornyCommandManager, MornyQueryManager}
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.messages.ThreadingManager
|
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.event.{MornyOnInlineQuery, MornyOnTelegramCommand, MornyOnUpdateTimestampOffsetLock}
|
||||||
import cc.sukazyo.cono.morny.core.bot.internal.{ErrorMessageManager, ThreadingManagerImpl}
|
import cc.sukazyo.cono.morny.core.bot.internal.{ErrorMessageManager, ThreadingManagerImpl}
|
||||||
@ -15,6 +15,7 @@ import cc.sukazyo.cono.morny.util.time.WatchDog
|
|||||||
import cc.sukazyo.cono.morny.util.GivenContext
|
import cc.sukazyo.cono.morny.util.GivenContext
|
||||||
import cc.sukazyo.cono.morny.util.UseString.MString
|
import cc.sukazyo.cono.morny.util.UseString.MString
|
||||||
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
|
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
|
||||||
|
import cc.sukazyo.cono.morny.util.hytrans.Translations
|
||||||
import com.pengrad.telegrambot.TelegramBot
|
import com.pengrad.telegrambot.TelegramBot
|
||||||
import com.pengrad.telegrambot.request.GetMe
|
import com.pengrad.telegrambot.request.GetMe
|
||||||
|
|
||||||
@ -127,6 +128,12 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
|||||||
)}
|
)}
|
||||||
|"""
|
|"""
|
||||||
|
|
||||||
|
///>>> BLOCK START local storage / data configuration
|
||||||
|
|
||||||
|
val lang: MornyLangs = MornyLangs()
|
||||||
|
|
||||||
|
///>>> BLOCK END local storage / data configuration
|
||||||
|
|
||||||
///>>> BLOCK START instance configure & startup stage 1
|
///>>> BLOCK START instance configure & startup stage 1
|
||||||
|
|
||||||
logger `info` "Coeur starting..."
|
logger `info` "Coeur starting..."
|
||||||
@ -324,6 +331,47 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
|||||||
|
|
||||||
///<<< BLOCK END instance configure & startup stage 2
|
///<<< BLOCK END instance configure & startup stage 2
|
||||||
|
|
||||||
|
/** Provide DSLs of Morny Coeur
|
||||||
|
*
|
||||||
|
* Provide the following coeur values to using/given context:
|
||||||
|
*
|
||||||
|
* - Coeur itself
|
||||||
|
* - its Telegram bot account: [[MornyCoeur.account]]
|
||||||
|
* - its i18n translation instance: [[MornyCoeur.lang.translations]]
|
||||||
|
*
|
||||||
|
* Also provides the DSLs defined in [[BotExtension]].
|
||||||
|
*
|
||||||
|
* You can simply add the following line to use the vals and DSL functions in your code:
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* // assuming the Coeur instance is coeur
|
||||||
|
* import coeur.dsl.given
|
||||||
|
*
|
||||||
|
* // now you can use the vals in your code
|
||||||
|
* translations.trans(/* ... */)
|
||||||
|
* // or use as an implicit/using value
|
||||||
|
* import com.pengrad.telegrambot.request.SendMessage
|
||||||
|
* import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
|
||||||
|
* SendMessage(/* ... */)
|
||||||
|
* .unsafeExecute // implicitly use coeur.account
|
||||||
|
*
|
||||||
|
* // you need to use the * import to use DSL functions
|
||||||
|
* import coeur.dsl.*
|
||||||
|
* // or use the following line to import both vals and DSL functions
|
||||||
|
* import coeur.dsl.{*, given}
|
||||||
|
*
|
||||||
|
* // now you can use the DSL functions in your code
|
||||||
|
* import com.pengrad.telegrambot.model.User
|
||||||
|
* val prefer_languge = user.asInstanceOf[User].prefer_language
|
||||||
|
*
|
||||||
|
* }}}
|
||||||
|
*/
|
||||||
|
object dsl extends BotExtension {
|
||||||
|
given coeur: MornyCoeur = MornyCoeur.this
|
||||||
|
given account: TelegramBot = MornyCoeur.this.account
|
||||||
|
given translations: Translations = MornyCoeur.this.lang.translations
|
||||||
|
}
|
||||||
|
|
||||||
def saveDataAll(): Unit = {
|
def saveDataAll(): Unit = {
|
||||||
modules.foreach(it => it.onRoutineSavingData)
|
modules.foreach(it => it.onRoutineSavingData)
|
||||||
logger `notice` "done all save action."
|
logger `notice` "done all save action."
|
||||||
@ -396,7 +444,8 @@ class MornyCoeur (modules: List[MornyModule])(using val config: MornyConfig)(tes
|
|||||||
logger `info` s"Succeed logged in to @${remote.username}"
|
logger `info` s"Succeed logged in to @${remote.username}"
|
||||||
break(Some(LoginResult(account, remote.username, remote.id)))
|
break(Some(LoginResult(account, remote.username, remote.id)))
|
||||||
} catch
|
} catch
|
||||||
case r: boundary.Break[Option[LoginResult]] => throw r
|
/* boundary.Break[Option[LoginResult] */
|
||||||
|
case r: boundary.Break[_] => throw r
|
||||||
case e: Throwable =>
|
case e: Throwable =>
|
||||||
logger `error`
|
logger `error`
|
||||||
s"""${e.toLogString}
|
s"""${e.toLogString}
|
||||||
|
68
src/main/scala/cc/sukazyo/cono/morny/core/MornyLangs.scala
Normal file
68
src/main/scala/cc/sukazyo/cono/morny/core/MornyLangs.scala
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package cc.sukazyo.cono.morny.core
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.core.Log.logger
|
||||||
|
import cc.sukazyo.cono.morny.data.MornyAssets
|
||||||
|
import cc.sukazyo.cono.morny.util.hytrans.*
|
||||||
|
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import scala.collection.mutable
|
||||||
|
import scala.util.boundary
|
||||||
|
import scala.util.boundary.break
|
||||||
|
|
||||||
|
class MornyLangs {
|
||||||
|
|
||||||
|
private val (lang_index, lang_trans) = {
|
||||||
|
|
||||||
|
logger `info` s"Loading Morny's translation data."
|
||||||
|
|
||||||
|
val (lang_dir, lang_index_content) = try {(
|
||||||
|
MornyAssets.pack.getResDir("langs"),
|
||||||
|
MornyAssets.pack.getResource("langs/_index.hyl").readAsString()
|
||||||
|
)} catch case e: IOException =>
|
||||||
|
throw Exception("Cannot read Morny's translations file.", e)
|
||||||
|
val my_index = LanguageTree.parseTreeDocument(lang_index_content)
|
||||||
|
val indexed_langs: Set[String] = {
|
||||||
|
val lang_tags = mutable.ListBuffer.empty[String]
|
||||||
|
my_index.root.traverseTree(lang_tags += _.langTag.lang)
|
||||||
|
logger `info` s"indexed following languages: ${lang_tags.mkString(", ")}"
|
||||||
|
lang_tags.toSet
|
||||||
|
}
|
||||||
|
|
||||||
|
val language_translations = mutable.HashMap.empty[String, Definitions]
|
||||||
|
|
||||||
|
for (file <- lang_dir.listFiles().filter(_.isFile)) 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_basename = file_name.dropRight(
|
||||||
|
if file_name.endsWith(".hyt") then ".hyt".length
|
||||||
|
else ".hytrans".length
|
||||||
|
)
|
||||||
|
val normalized = LangTag.normalizeLangTag(file_basename)
|
||||||
|
if !indexed_langs.contains(normalized) then
|
||||||
|
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()
|
||||||
|
Parser.parse(content)
|
||||||
|
} catch case e: IOException =>
|
||||||
|
logger `error`
|
||||||
|
s"""Failed read/parse translation file $file_name (normalized lang name is $normalized):
|
||||||
|
|${e.toLogString.indent(2)}
|
||||||
|
|due to failed, this ($file_name) has been ignored.""".stripMargin
|
||||||
|
break()
|
||||||
|
logger `info` s"read language file $file_name (normalized lang name is $normalized), with ${lang_def.size} entries."
|
||||||
|
if language_translations contains normalized then
|
||||||
|
// TODO: merge
|
||||||
|
logger `warn` s" language $normalized seems already loaded one yet, this will override the old one!"
|
||||||
|
else language_translations += (normalized -> lang_def)
|
||||||
|
}}
|
||||||
|
|
||||||
|
(my_index, language_translations.toMap)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val translations: Translations = Translations(lang_index, lang_trans)
|
||||||
|
|
||||||
|
}
|
@ -2,10 +2,13 @@ package cc.sukazyo.cono.morny.core.bot.api
|
|||||||
|
|
||||||
import cc.sukazyo.cono.morny.core.MornyCoeur
|
import cc.sukazyo.cono.morny.core.MornyCoeur
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.messages.ErrorMessage
|
import cc.sukazyo.cono.morny.core.bot.api.messages.ErrorMessage
|
||||||
|
import cc.sukazyo.cono.morny.util.hytrans.LangTag
|
||||||
|
import com.pengrad.telegrambot.model.User
|
||||||
|
|
||||||
/** Bot extensions for Morny feature.
|
object BotExtension extends BotExtension
|
||||||
*/
|
|
||||||
object BotExtension {
|
/** Bot extensions for Morny feature. */
|
||||||
|
trait BotExtension {
|
||||||
|
|
||||||
extension (errorMessage: ErrorMessage[?, ?]) {
|
extension (errorMessage: ErrorMessage[?, ?]) {
|
||||||
|
|
||||||
@ -21,4 +24,13 @@ object BotExtension {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension (user: User) {
|
||||||
|
|
||||||
|
def prefer_language: String =
|
||||||
|
user.languageCode match
|
||||||
|
case null => ""
|
||||||
|
case x => LangTag.normalizeLangTag(x)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,35 +2,30 @@ package cc.sukazyo.cono.morny.core.bot.command
|
|||||||
|
|
||||||
import cc.sukazyo.cono.morny.core.MornyCoeur
|
import cc.sukazyo.cono.morny.core.MornyCoeur
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
|
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
|
||||||
import cc.sukazyo.cono.morny.data.MornyInformation.{getAboutPic, getMornyAboutLinksHTML}
|
import cc.sukazyo.cono.morny.data.MornyInformation.{getAboutPic, getMornyAboutLinksVars}
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
|
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
|
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
|
||||||
import com.pengrad.telegrambot.model.Update
|
import com.pengrad.telegrambot.model.Update
|
||||||
import com.pengrad.telegrambot.model.request.ParseMode
|
import com.pengrad.telegrambot.model.request.ParseMode
|
||||||
import com.pengrad.telegrambot.request.SendPhoto
|
import com.pengrad.telegrambot.request.SendPhoto
|
||||||
import com.pengrad.telegrambot.TelegramBot
|
|
||||||
|
|
||||||
class MornyInfoOnStart (using coeur: MornyCoeur) extends ISimpleCommand {
|
class MornyInfoOnStart (using coeur: MornyCoeur) extends ISimpleCommand {
|
||||||
private given TelegramBot = coeur.account
|
import coeur.dsl.{*, given}
|
||||||
|
|
||||||
override val name: String = "start"
|
override val name: String = "start"
|
||||||
override val aliases: List[ICommandAlias] = Nil
|
override val aliases: List[ICommandAlias] = Nil
|
||||||
|
|
||||||
override def execute (using command: InputCommand, event: Update): Unit = {
|
override def execute (using command: InputCommand, event: Update): Unit = {
|
||||||
|
|
||||||
|
given lang: String = event.message.from.prefer_language
|
||||||
SendPhoto(
|
SendPhoto(
|
||||||
event.message.chat.id,
|
event.message.chat.id,
|
||||||
getAboutPic
|
getAboutPic
|
||||||
).caption(
|
).caption(
|
||||||
s"""欢迎使用 <b>Morny Cono</b>,<i>来自安妮的侍从小鼠</i>。
|
translations.trans(
|
||||||
|Morny 具有各种各样的功能。
|
"morny.command.info.sub_start.message",
|
||||||
|
|
translations.transAsVar("morny.information.about_links", getMornyAboutLinksVars*)
|
||||||
|————————————————
|
).stripMargin
|
||||||
|$getMornyAboutLinksHTML
|
|
||||||
|————————————————
|
|
||||||
|
|
|
||||||
|(你可以随时通过 /info 重新获得这些信息)"""
|
|
||||||
.stripMargin
|
|
||||||
).parseMode(ParseMode HTML)
|
).parseMode(ParseMode HTML)
|
||||||
.unsafeExecute
|
.unsafeExecute
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package cc.sukazyo.cono.morny.core.bot.command
|
|||||||
import cc.sukazyo.cono.morny.core.{MornyCoeur, MornySystem}
|
import cc.sukazyo.cono.morny.core.{MornyCoeur, MornySystem}
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ITelegramCommand}
|
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ITelegramCommand}
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
|
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
|
||||||
import cc.sukazyo.cono.morny.core.Log.logger
|
|
||||||
import cc.sukazyo.cono.morny.data.MornyInformation.*
|
import cc.sukazyo.cono.morny.data.MornyInformation.*
|
||||||
import cc.sukazyo.cono.morny.data.TelegramStickers
|
import cc.sukazyo.cono.morny.data.TelegramStickers
|
||||||
import cc.sukazyo.cono.morny.reporter.MornyReport
|
import cc.sukazyo.cono.morny.reporter.MornyReport
|
||||||
@ -16,11 +15,11 @@ import cc.sukazyo.cono.morny.util.var_text.VarText
|
|||||||
import com.pengrad.telegrambot.model.Update
|
import com.pengrad.telegrambot.model.Update
|
||||||
import com.pengrad.telegrambot.model.request.ParseMode
|
import com.pengrad.telegrambot.model.request.ParseMode
|
||||||
import com.pengrad.telegrambot.request.{SendMessage, SendPhoto, SendSticker}
|
import com.pengrad.telegrambot.request.{SendMessage, SendPhoto, SendSticker}
|
||||||
import com.pengrad.telegrambot.TelegramBot
|
|
||||||
|
|
||||||
import java.lang.System
|
import java.lang.System
|
||||||
|
|
||||||
class MornyInformation (using coeur: MornyCoeur) extends ITelegramCommand {
|
class MornyInformation (using coeur: MornyCoeur) extends ITelegramCommand {
|
||||||
private given TelegramBot = coeur.account
|
import coeur.dsl.{*, given}
|
||||||
|
|
||||||
private case object Subs {
|
private case object Subs {
|
||||||
val STICKERS = "stickers"
|
val STICKERS = "stickers"
|
||||||
@ -76,19 +75,10 @@ class MornyInformation (using coeur: MornyCoeur) extends ITelegramCommand {
|
|||||||
cxt.bind_chat.id,
|
cxt.bind_chat.id,
|
||||||
getAboutPic
|
getAboutPic
|
||||||
).caption(
|
).caption(
|
||||||
// language=html
|
translations.trans(
|
||||||
(VarText(
|
"morny.command.info.message.about",
|
||||||
"""<b>Morny Cono</b>
|
translations.transAsVar("morny.information.about_links", getMornyAboutLinksVars*)(using cxt.bind_message.from.prefer_language)
|
||||||
|来自安妮的侍从小鼠。
|
)(using cxt.bind_message.from.prefer_language)
|
||||||
|————————————————
|
|
||||||
|{about_links}""".stripMargin
|
|
||||||
).render(
|
|
||||||
"about_links" -> getMornyAboutLinksHTML
|
|
||||||
) :: Nil)
|
|
||||||
.map( f =>
|
|
||||||
logger `trace` f
|
|
||||||
f
|
|
||||||
).head
|
|
||||||
).parseMode(ParseMode HTML).replyToMessageId(cxt.bind_message.messageId)
|
).parseMode(ParseMode HTML).replyToMessageId(cxt.bind_message.messageId)
|
||||||
.unsafeExecute
|
.unsafeExecute
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package cc.sukazyo.cono.morny.data
|
package cc.sukazyo.cono.morny.data
|
||||||
|
|
||||||
import cc.sukazyo.cono.morny.core.{MornyAbout, MornySystem}
|
import cc.sukazyo.cono.morny.core.{MornyAbout, MornySystem}
|
||||||
import cc.sukazyo.cono.morny.util.var_text.VarText
|
import cc.sukazyo.cono.morny.util.var_text.Var
|
||||||
|
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.rmi.UnknownHostException
|
import java.rmi.UnknownHostException
|
||||||
@ -39,13 +39,8 @@ object MornyInformation {
|
|||||||
|
|
||||||
def getAboutPic: Array[Byte] = TelegramImages.IMG_ABOUT get
|
def getAboutPic: Array[Byte] = TelegramImages.IMG_ABOUT get
|
||||||
|
|
||||||
def getMornyAboutLinksHTML: String =
|
def getMornyAboutLinksVars: List[Var] =
|
||||||
VarText(
|
List(
|
||||||
// language=html
|
|
||||||
"""<a href='{MORNY_SOURCECODE_LINK}'>source code</a> | <a href='{MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK}'>backup</a>
|
|
||||||
|<a href='{MORNY_ISSUE_TRACKER_LINK}'>反馈 / issue tracker</a>
|
|
||||||
|<a href='{MORNY_USER_GUIDE_LINK}'>使用说明书 / user guide & docs</a>""".stripMargin
|
|
||||||
).render(
|
|
||||||
"MORNY_SOURCECODE_LINK" -> MornyAbout.MORNY_SOURCECODE_LINK,
|
"MORNY_SOURCECODE_LINK" -> MornyAbout.MORNY_SOURCECODE_LINK,
|
||||||
"MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK" -> MornyAbout.MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK,
|
"MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK" -> MornyAbout.MORNY_SOURCECODE_SELF_HOSTED_MIRROR_LINK,
|
||||||
"MORNY_ISSUE_TRACKER_LINK" -> MornyAbout.MORNY_ISSUE_TRACKER_LINK,
|
"MORNY_ISSUE_TRACKER_LINK" -> MornyAbout.MORNY_ISSUE_TRACKER_LINK,
|
||||||
|
@ -3,29 +3,26 @@ package cc.sukazyo.cono.morny.morny_misc
|
|||||||
import cc.sukazyo.cono.morny.core.MornyCoeur
|
import cc.sukazyo.cono.morny.core.MornyCoeur
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
|
import cc.sukazyo.cono.morny.core.bot.api.{ICommandAlias, ISimpleCommand}
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
|
import cc.sukazyo.cono.morny.core.bot.api.messages.{ErrorMessage, MessagingContext}
|
||||||
import cc.sukazyo.cono.morny.core.bot.api.BotExtension.submit
|
|
||||||
import cc.sukazyo.cono.morny.data.TelegramStickers
|
import cc.sukazyo.cono.morny.data.TelegramStickers
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
|
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
|
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.unsafeExecute
|
||||||
import com.pengrad.telegrambot.model.{Message, Update}
|
import com.pengrad.telegrambot.model.{Message, Update}
|
||||||
import com.pengrad.telegrambot.model.request.ParseMode
|
import com.pengrad.telegrambot.model.request.ParseMode
|
||||||
import com.pengrad.telegrambot.request.{SendMessage, SendSticker}
|
import com.pengrad.telegrambot.request.{SendMessage, SendSticker}
|
||||||
import com.pengrad.telegrambot.TelegramBot
|
|
||||||
|
|
||||||
class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
|
class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
|
||||||
private given TelegramBot = coeur.account
|
import coeur.dsl.{*, given}
|
||||||
|
|
||||||
override val name: String = "test"
|
override val name: String = "test"
|
||||||
override val aliases: List[ICommandAlias] = Nil
|
override val aliases: List[ICommandAlias] = Nil
|
||||||
|
|
||||||
override def execute (using command: InputCommand, event: Update): Unit = {
|
override def execute (using command: InputCommand, event: Update): Unit = {
|
||||||
given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using event.message)
|
given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using event.message)
|
||||||
|
given lang: String = context.bind_user.prefer_language
|
||||||
|
|
||||||
SendMessage(
|
SendMessage(
|
||||||
event.message.chat.id,
|
event.message.chat.id,
|
||||||
// language=html
|
translations.trans("morny.misc.command_test.message")
|
||||||
"<b>Just</b> a TEST command.\n"
|
|
||||||
+ "Please input something to test the command."
|
|
||||||
).replyToMessageId(event.message.messageId).parseMode(ParseMode HTML)
|
).replyToMessageId(event.message.messageId).parseMode(ParseMode HTML)
|
||||||
.unsafeExecute
|
.unsafeExecute
|
||||||
|
|
||||||
@ -34,11 +31,13 @@ class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def execute2 (message: Message, previousContext: MessagingContext.WithUserAndMessage): Unit = {
|
private def execute2 (message: Message, previousContext: MessagingContext.WithUserAndMessage): Unit = {
|
||||||
|
given context: MessagingContext.WithUserAndMessage = MessagingContext.extract(using message)
|
||||||
|
given lang: String = context.bind_user.prefer_language
|
||||||
|
|
||||||
if (message.text == "oops")
|
if (message.text == "oops")
|
||||||
SendMessage(
|
SendMessage(
|
||||||
message.chat.id,
|
message.chat.id,
|
||||||
"A test error message will be generated."
|
translations.trans("morny.misc.command_test.branch_oops.err_message_simple")
|
||||||
).replyToMessageId(message.messageId)
|
).replyToMessageId(message.messageId)
|
||||||
.unsafeExecute
|
.unsafeExecute
|
||||||
ErrorMessage(
|
ErrorMessage(
|
||||||
@ -48,16 +47,17 @@ class Testing (using coeur: MornyCoeur) extends ISimpleCommand {
|
|||||||
).replyToMessageId(message.messageId),
|
).replyToMessageId(message.messageId),
|
||||||
_complex = SendMessage(
|
_complex = SendMessage(
|
||||||
message.chat.id,
|
message.chat.id,
|
||||||
"Oops: There is just a test error."
|
translations.trans("morny.misc.command_test.branch_oops.err_message_complex")
|
||||||
).replyToMessageId(message.messageId)
|
).replyToMessageId(message.messageId)
|
||||||
)(using MessagingContext.extract(using message))
|
).submit
|
||||||
.submit
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendMessage(
|
SendMessage(
|
||||||
message.chat.id,
|
message.chat.id,
|
||||||
// language=html
|
translations.trans(
|
||||||
"<b><u>Test command with following input:</u></b>\n" + message.text
|
"morny.misc.command_test.branch_normal.message",
|
||||||
|
"replied_message" -> message.text
|
||||||
|
)
|
||||||
).replyToMessageId(message.messageId).parseMode(ParseMode HTML)
|
).replyToMessageId(message.messageId).parseMode(ParseMode HTML)
|
||||||
.unsafeExecute
|
.unsafeExecute
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ object Parser {
|
|||||||
case Some(' ') | Some('\t') | None => // empty lines, will be ignored
|
case Some(' ') | Some('\t') | None => // empty lines, will be ignored
|
||||||
case Some('#') => // comment line, will be ignored
|
case Some('#') => // comment line, will be ignored
|
||||||
case Some('%') => // document meta definition line, currently not supported
|
case Some('%') => // document meta definition line, currently not supported
|
||||||
|
case Some('&') => // document meta definition line, currently not supported
|
||||||
case Some('|') => // content line
|
case Some('|') => // content line
|
||||||
addLine(line drop 2)
|
addLine(line drop 2)
|
||||||
case Some(_) => // a key definition line
|
case Some(_) => // a key definition line
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cc.sukazyo.cono.morny.util.hytrans
|
package cc.sukazyo.cono.morny.util.hytrans
|
||||||
|
|
||||||
import cc.sukazyo.cono.morny.util.var_text.{Var, VarText}
|
import cc.sukazyo.cono.morny.util.var_text.{Var, VarText}
|
||||||
|
import cc.sukazyo.cono.morny.util.var_text.Var.String_As_VarText
|
||||||
|
|
||||||
import scala.util.boundary
|
import scala.util.boundary
|
||||||
|
|
||||||
@ -42,4 +43,7 @@ class Translations (
|
|||||||
def trans (key: String, args: Var*)(using lang: String): String =
|
def trans (key: String, args: Var*)(using lang: String): String =
|
||||||
trans(key).render(args*)
|
trans(key).render(args*)
|
||||||
|
|
||||||
|
def transAsVar (key: String, args: Var*)(using lang: String): Var =
|
||||||
|
trans(key, args*).asVar(key)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import scala.language.implicitConversions
|
|||||||
*
|
*
|
||||||
* You can just call the [[Var]] constructor to create a new Var, or use the implicit
|
* You can just call the [[Var]] constructor to create a new Var, or use the implicit
|
||||||
* conversion to create a var from a tuple of ([[String]], [[String]]), or use the extension
|
* conversion to create a var from a tuple of ([[String]], [[String]]), or use the extension
|
||||||
* method [[Var.StringAsVarText.asVar]] to convert a [[String]] to a var.
|
* method [[Var.String_As_VarText.asVar]] to convert a [[String]] to a var.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*
|
*
|
||||||
@ -77,11 +77,11 @@ object Var {
|
|||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
implicit def StrStrTupleAsVar (tuple: (String, Any)): Var =
|
implicit def StrStrTuple_as_Var (tuple: (String, Any)): Var =
|
||||||
Var(tuple._1, tuple._2.toString)
|
Var(tuple._1, tuple._2.toString)
|
||||||
|
|
||||||
/** @see [[asVar]] */
|
/** @see [[asVar]] */
|
||||||
implicit class StringAsVarText (text: String):
|
implicit class String_As_VarText (text: String):
|
||||||
/** Convert this string text to a [[Var]].
|
/** Convert this string text to a [[Var]].
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
* @param id the var-id.
|
* @param id the var-id.
|
||||||
|
@ -2,6 +2,8 @@ package cc.sukazyo.cono.morny.util.var_text
|
|||||||
|
|
||||||
import cc.sukazyo.cono.morny.util.var_text.Var.isLegalId
|
import cc.sukazyo.cono.morny.util.var_text.Var.isLegalId
|
||||||
|
|
||||||
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
/** A text/string template that may contains some named replaceable variables. It's concept may
|
/** A text/string template that may contains some named replaceable variables. It's concept may
|
||||||
* be similar with scala's `StringContext` or `GString` in groovy.
|
* be similar with scala's `StringContext` or `GString` in groovy.
|
||||||
*
|
*
|
||||||
@ -56,6 +58,9 @@ object VarText {
|
|||||||
def apply (_nodes: VTNode*): VarText = new VarText:
|
def apply (_nodes: VTNode*): VarText = new VarText:
|
||||||
override val nodes: List[VTNode] = _nodes.toList
|
override val nodes: List[VTNode] = _nodes.toList
|
||||||
|
|
||||||
|
implicit def VarText_is_String (varText: VarText): String =
|
||||||
|
varText.render()
|
||||||
|
|
||||||
private val symbol_escape = '/'
|
private val symbol_escape = '/'
|
||||||
private val symbol_var_start = '{'
|
private val symbol_var_start = '{'
|
||||||
private val symbol_var_end = '}'
|
private val symbol_var_end = '}'
|
||||||
|
Loading…
Reference in New Issue
Block a user