add some scaladoc and add IDEA/VSCode configures

This commit is contained in:
A.C.Sukazyo Eyre 2024-05-21 15:43:48 +08:00
parent 053b789aff
commit a62398e0c5
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
19 changed files with 358 additions and 3 deletions

2
.gitignore vendored
View File

@ -1,7 +1,5 @@
# IDE # IDE
.idea/
.vscode/
.gradle/ .gradle/
.settings/ .settings/
.metals/ .metals/

BIN
.idea/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

1
.run/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
debug.env

View File

@ -0,0 +1,16 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Morny CLI [pr]" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="cc.sukazyo.cono.morny.MornyCLI" />
<module name="Coeur Morny Cono" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/run" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value=".*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Morny Coeur [t][user:dev(env).u|q|c|r:m] [pr]" type="Application" factoryName="Application">
<option name="envFilePaths">
<option value="$PROJECT_DIR$/.run/debug.env" />
</option>
<option name="MAIN_CLASS_NAME" value="cc.sukazyo.cono.morny.core.ServerMain" />
<module name="Coeur Morny Cono" />
<option name="PROGRAM_PARAMETERS" value="--quiet --debug -t --username sukazyo_deving_bot --master 793274677 --trusted-chat -1 --auto-cmd --outdated-block --trusted-reader-dinner 1040613596 --report-to 793274677 -medc 793274677 -medt 0,2,18,19 -medtz 8 --dinner-chat -1001670950261" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/run" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value=".*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Morny Coeur [user:dev(env).u|q|c] [pr]" type="Application" factoryName="Application">
<option name="envFilePaths">
<option value="$PROJECT_DIR$/.run/debug.env" />
</option>
<option name="MAIN_CLASS_NAME" value="cc.sukazyo.cono.morny.core.ServerMain" />
<module name="Coeur Morny Cono" />
<option name="PROGRAM_PARAMETERS" value="--quiet --debug --username sukazyo_deving_bot --master 793274677 --trusted-chat -1 --outdated-block --trusted-reader-dinner 1040613596 -medc 793274677 -medt 0,2,18,19 -medtz 8 --dinner-chat -1001670950261" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/run" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value=".*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Morny Coeur [user:dev(env).u|q|c|r:m] [pr]" type="Application" factoryName="Application">
<option name="envFilePaths">
<option value="$PROJECT_DIR$/.run/debug.env" />
</option>
<option name="MAIN_CLASS_NAME" value="cc.sukazyo.cono.morny.core.ServerMain" />
<module name="Coeur Morny Cono" />
<option name="PROGRAM_PARAMETERS" value="--quiet --debug --username sukazyo_deving_bot --master 793274677 --trusted-chat -1 --auto-cmd --outdated-block --trusted-reader-dinner 1040613596 --report-to 793274677 -medc 793274677 -medt 0,2,18,19 -medtz 8 --dinner-chat -1001670950261" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/run" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value=".*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,31 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="MornyTests #ALL" type="ScalaTestRunConfiguration" factoryName="ScalaTest" singleton="false" show_console_on_std_err="false" show_console_on_std_out="false">
<module name="Coeur Morny Cono" />
<option name="VMParameters" value="" />
<option name="allowRunningInParallel" value="true" />
<option name="alternativeJrePath" />
<option name="alternativeJrePathEnabled" value="false" />
<option name="classpathModifications">
<list />
</option>
<option name="envs">
<map />
</option>
<option name="passParentEnvs" value="true" />
<option name="programParameters" value="" />
<option name="projectPathOnTarget" />
<option name="selectedOptions">
<list />
</option>
<option name="testKind" value="All in package" />
<option name="workingDirectory" value="$ProjectFileDir$\run" />
<option name="searchTest" value="In single module" />
<option name="shortenClasspath" value="NONE" />
<option name="testPackagePath" value="cc.sukazyo.cono.morny.test" />
<option name="useUiWithSbt" value="true" />
<option name="workingDirectory" value="$ProjectFileDir$\run" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ServerMain [only-hello]" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="cc.sukazyo.cono.morny.core.ServerMain" />
<module name="Coeur Morny Cono" />
<option name="PROGRAM_PARAMETERS" value="--only-hello" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/run" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value=".*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ServerMain [version]" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="cc.sukazyo.cono.morny.core.ServerMain" />
<module name="Coeur Morny Cono" />
<option name="PROGRAM_PARAMETERS" value="--version" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/run" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value=".*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

1
.run/debug.env.example Normal file
View File

@ -0,0 +1 @@
MORNY_TG_TOKEN="2001015432:ABCDEFGH01234567890123456790123456"

9
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"recommendations": [
"scalameta.metals",
"scala-lang.scala",
"scala-lang.scala-snippets",
"streetsidesoftware.code-spell-checker",
"vscjava.vscode-java-pack"
]
}

57
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,57 @@
{
// 使 IntelliSense
//
// : https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Morny Coeur [user:dev|q|d|mm|tc:rm|ac|ob|trd|dc|r:m|med] [pr]",
"type": "java",
"request": "launch",
"projectName": "Coeur Morny Cono",
"cwd": "${workspaceFolder}/run",
"mainClass": "cc.sukazyo.cono.morny.ServerMain",
"vmArgs": ["-Djava.net.useSystemProxies=true"],
"envFile": "${workspaceFolder}/.run/debug.env",
"args": [
"--quiet",
"--debug",
"--username", "sukazyo_deving_bot",
"--master", "793274677",
"--trusted-chat", "-1",
"--auto-cmd",
"--outdated-block",
"--trusted-reader-dinner", "1040613596",
"--dinner-chat", "-1001670950261",
"--report-to", "793274677",
"-medc", "793274677", "-medt", "0,2,18,19", "-medtz", "8",
]
},
{
"name": "Morny Test [pr]",
"type": "java",
"request": "launch",
"cwd": "${workspaceFolder}/run",
"vmArgs": ["-Djava.net.useSystemProxies=true"],
"projectName": "Coeur Morny Cono",
"mainClass": "cc.sukazyo.cono.morny.MornyTest",
},
{
"name": "UniversalTest [pr]",
"type": "java",
"request": "launch",
"cwd": "${workspaceFolder}/run",
"vmArgs": ["-Djava.net.useSystemProxies=true"],
"projectName": "Coeur Morny Cono",
"mainClass": "cc.sukazyo.cono.morny.UniversalTest",
},
{
"name": "Current File [pr]",
"type": "java",
"request": "launch",
"cwd": "${workspaceFolder}/run",
"vmArgs": ["-Djava.net.useSystemProxies=true"],
"mainClass": "${file}"
},
]
}

14
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"java.dependency.packagePresentation": "hierarchical",
"java.configuration.updateBuildConfiguration": "disabled",
"java.compile.nullAnalysis.mode": "disabled",
"files.watcherExclude": {
"**/target": true
},
"cSpell.words": [
"Coeur",
"Gson",
"Morny",
"userid"
]
}

View File

@ -4,8 +4,10 @@ import cc.sukazyo.cono.morny.core.internal.logging.{MornyFormatterConsole, Morny
import cc.sukazyo.messiva.appender.ConsoleAppender import cc.sukazyo.messiva.appender.ConsoleAppender
import cc.sukazyo.messiva.log.LogLevels import cc.sukazyo.messiva.log.LogLevels
/** Logger controller of Morny Coeur program */
object Log { object Log {
/** The logger that Morny will use */
val logger: MornyLoggerBase = MornyLoggerBase( val logger: MornyLoggerBase = MornyLoggerBase(
ConsoleAppender( ConsoleAppender(
MornyFormatterConsole() MornyFormatterConsole()
@ -13,8 +15,14 @@ object Log {
) )
logger.minLevel(LogLevels.INFO) logger.minLevel(LogLevels.INFO)
/** If the debug level logging is enabled
*
* @return `true` when the debug logging is enabled, `false` otherwise.
*/
def debug: Boolean = logger.levelSetting.minLevel.level <= LogLevels.DEBUG.level def debug: Boolean = logger.levelSetting.minLevel.level <= LogLevels.DEBUG.level
/** Set if the debug logging should be enabled.
*/
def debug (is: Boolean): Unit = def debug (is: Boolean): Unit =
if is then logger.minLevel(LogLevels.ALL) if is then logger.minLevel(LogLevels.ALL)
else logger.minLevel(LogLevels.INFO) else logger.minLevel(LogLevels.INFO)

View File

@ -13,24 +13,100 @@ import java.security.NoSuchAlgorithmException
object MornySystem { object MornySystem {
/** The normal version string without extra context (`+000` fields).
*
* Should contains base version ([[VERSION_BASE]]), with additional [[VERSION_DELTA version delta]]
* or snapshot tag if exists.
*
* For example `1.0.0`, `2.1.1-beta2`, `0.19.2-SNAPSHOT`, `2.0.0-alpha19-SNAPSHOT`
*/
@BuildConfigField val VERSION: String = BuildConfig.VERSION @BuildConfigField val VERSION: String = BuildConfig.VERSION
/** The full specific version string with extra context (`+000` fields).
*
* Should contains all the normal version ([[VERSION]]), additional with git commit hash
* if exists.
*
* For example `2.0.0-alpha19-SNAPSHOT+git254ec2a5`
*/
@BuildConfigField val VERSION_FULL: String = BuildConfig.VERSION_FULL @BuildConfigField val VERSION_FULL: String = BuildConfig.VERSION_FULL
/** The base version string.
*
* Contains only the main version number (0.0.0) and alpha/beta/RC version (-alpha20). NO
* snapshot tag or [[VERSION_DELTA version delta]] is included.
*/
@BuildConfigField val VERSION_BASE: String = BuildConfig.VERSION_BASE @BuildConfigField val VERSION_BASE: String = BuildConfig.VERSION_BASE
/** The version delta string if exists.
*
* This delta is for debug purpose when it is designed, it adds a field to the normal
* version string to help shows if the code is updated in debug environment.
*
* The standard version delta is a string starts with `-ð`, attached after the
* [[VERSION_BASE base version]].
*
* It is currently not in used in official environment yet.
*/
@BuildConfigField val VERSION_DELTA: Option[String] = BuildConfig.VERSION_DELTA @BuildConfigField val VERSION_DELTA: Option[String] = BuildConfig.VERSION_DELTA
/** The full length git commit id that this build is based on.
*
* Along the workspace is in a checked out git repo, this field will be the currently checked
* out git commit, no matter the git repo is clean or not.
*
* Only exists when this is built with git repo, if there's no git repo, this will only be
* [[None]].
*/
@BuildConfigField val GIT_COMMIT: Option[String] = Some(BuildConfig.COMMIT) @BuildConfigField val GIT_COMMIT: Option[String] = Some(BuildConfig.COMMIT)
/** The build time in [[EpochMillis]].
*
* If this build is built with a git repo and the git repo is clean, that means the source
* code should have no changes with [[GIT_COMMIT the currently checked out git commit]],
* then we call this is a **clean build**, and this timestamp will be the [[GIT_COMMIT]]'s
* commit timestamp. This can help us to do a *reproducible build*.
*
* On any other cases, this timestamp will be the [[System.currentTimeMillis]] when the
* `sbt compile` is called.
*/
@BuildConfigField val CODE_TIMESTAMP: EpochMillis = BuildConfig.CODE_TIMESTAMP @BuildConfigField val CODE_TIMESTAMP: EpochMillis = BuildConfig.CODE_TIMESTAMP
/** The codename of this version.
*
* Usually a city name, and usually updates on and only on the minor version (X.Y.z) level
* update.
*
* Should be a lowercased english only string (maybe contains numbers at some point, at
* least not historically).
*/
@BuildConfigField val CODENAME: String = BuildConfig.CODENAME @BuildConfigField val CODENAME: String = BuildConfig.CODENAME
/** The HTTP url that a git repository of this project can be found.
*/
@BuildConfigField val CODE_STORE: String = BuildConfig.CODE_STORE @BuildConfigField val CODE_STORE: String = BuildConfig.CODE_STORE
/** The string template that the commit url of this build can be found.
*
* Should contains one `%s` placeholder, can be interpolated a [[GIT_COMMIT]] to get the
* page of commit that current build based on.
*/
//noinspection ScalaWeakerAccess //noinspection ScalaWeakerAccess
@BuildConfigField val COMMIT_PATH: String = BuildConfig.COMMIT_PATH @BuildConfigField val COMMIT_PATH: String = BuildConfig.COMMIT_PATH
/** If this build is built with a clean git repo. */
@BuildConfigField @BuildConfigField
def isCleanBuild: Boolean = BuildConfig.CLEAN_BUILD def isCleanBuild: Boolean = BuildConfig.CLEAN_BUILD
/** The HTTP url of git commit which this build is based on.
*
* Based on [[GIT_COMMIT]] and [[COMMIT_PATH]].
*/
def currentCodePath: String|Null = def currentCodePath: String|Null =
if ((COMMIT_PATH eq null) || (GIT_COMMIT isEmpty)) null if ((COMMIT_PATH eq null) || (GIT_COMMIT isEmpty)) null
else COMMIT_PATH.formatted(GIT_COMMIT get) else COMMIT_PATH.formatted(GIT_COMMIT get)
/** The MD5 hash of current running coeur execution jar.
*
* Only works on the current running coeur is from a jar file.
*
* If read jar file failed, it possibly means currently is not run from a jar file, then
* this will return `"<non-jar-runtime>"`.
*
* If failed on calculating MD5 hash, it will return `"<calculation-error>"`.
*/
def getJarMD5: String = { def getJarMD5: String = {
try { try {
FileUtils.getMD5Three(MornySystem.getClass.getProtectionDomain.getCodeSource.getLocation.toURI.getPath) FileUtils.getMD5Three(MornySystem.getClass.getProtectionDomain.getCodeSource.getLocation.toURI.getPath)

View File

@ -26,6 +26,19 @@ trait BotExtension {
extension (user: User) { extension (user: User) {
/** Get this telegram [[User]]'s prefer language.
*
* It will check the [[User.languageCode]] provided by Telegram API.
*
* If a language code is provided, it will be [[LangTag.normalizeLangTag normalized]]
* to [[LangTag]] and return.
*
* If cannot find a language code associated with this [[User]], the empty string will
* be return.
*
* @return A [[LangTag.normalizeLangTag normalized]] [[LangTag]] that should be this
* [[User]]'s prefer language, or a empty string.
*/
def prefer_language: String = def prefer_language: String =
user.languageCode match user.languageCode match
case null => "" case null => ""

View File

@ -27,9 +27,28 @@ import com.pengrad.telegrambot.request.AbstractSendRequest
*/ */
trait ErrorMessage[T1 <: AbstractSendRequest[T1], T2 <: AbstractSendRequest[T2]] { trait ErrorMessage[T1 <: AbstractSendRequest[T1], T2 <: AbstractSendRequest[T2]] {
/** The simple variant of this error message.
*
* In Morny, this is usually a sticker that shows the generic type of the error.
*
* Can be get by using [[getByType]] with variant tag [[ErrorMessage.Types.Simple]]
* @since 2.0.0
*/
val simple: T1 val simple: T1
/** The complex variant of this error message.
*
* In Morny, this should be a text-based message that shows key information of the error
* which want to describe.
*
* Can be get by using [[getByType]] with variant tag [[ErrorMessage.Types.Complex]]
* @since 2.0.0
*/
val complex: T2 val complex: T2
/** An context that defines where this error message belongs. Will be used to publish this
* message (aka. send message).
* @since 2.0.0
*/
val context: MessagingContext.WithMessage val context: MessagingContext.WithMessage
/** Get the simple or complex message by the given [[ErrorMessage.Types]] infer. /** Get the simple or complex message by the given [[ErrorMessage.Types]] infer.
@ -58,12 +77,30 @@ trait ErrorMessage[T1 <: AbstractSendRequest[T1], T2 <: AbstractSendRequest[T2]]
} }
/** @see [[ErrorMessage]] */
object ErrorMessage { object ErrorMessage {
/** An enum that contains the tag of an [[ErrorMessage]]'s variant type.
*
* Can be used to get the specific type's message of that type using [[ErrorMessage.getByType]].
*
* @since 2.0.0
*/
enum Types: enum Types:
/** @see [[ErrorMessage.simple]] */
case Simple case Simple
/** @see [[ErrorMessage.complex]] */
case Complex case Complex
/** A new [[ErrorMessage]].
*
* @since 2.0.0
* @see [[ErrorMessage]]
*
* @param _simple The [[ErrorMessage.simple]] message of this error message.
* @param _complex The [[ErrorMessage.complex]] message of this error message.
* @param cxt The context of this error message, defines where the error message belongs.
*/
def apply [T1 <: AbstractSendRequest[T1], T2<: AbstractSendRequest[T2]] def apply [T1 <: AbstractSendRequest[T1], T2<: AbstractSendRequest[T2]]
(_simple: T1, _complex: T2)(using cxt: MessagingContext.WithMessage): ErrorMessage[T1, T2] = (_simple: T1, _complex: T2)(using cxt: MessagingContext.WithMessage): ErrorMessage[T1, T2] =
new ErrorMessage[T1, T2]: new ErrorMessage[T1, T2]:

View File

@ -6,7 +6,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* 这个注解表示当前字段是由 gradle 任务 {@code generateBuildConfig} 自动生成的. * The annotation indicates that the field is generated by the sbt plugin {@code sbtBuildInfo}.
* @since 1.0.0-alpha4 * @since 1.0.0-alpha4
*/ */
@Documented @Documented