diff --git a/build.gradle b/build.gradle
index 60a856a..21ab1a4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,7 +14,9 @@ plugins {
}
final boolean proj_git = grgit!=null
+final String proj_store = MORNY_CODE_STORE
final String proj_commit = proj_git ? grgit.head().id : null
+final String proj_commit_path = MORNY_COMMIT_PATH
final boolean proj_clean = isCleanBuild()
if (!proj_git)
print "[MornyBuild] git repository not available for current working space! git version tag will be disabled."
@@ -120,11 +122,14 @@ buildConfig {
packageName(proj_package)
buildConfigField('String', 'VERSION', "\"${proj_version}\"")
+ buildConfigField('String', 'VERSION_BASE', "\"${proj_version_base}\"")
buildConfigField('String', 'VERSION_DELTA', proj_version_use_delta ? "\"${proj_version_delta}\"" : "null")
buildConfigField('String', 'CODENAME', "\"${proj_version_codename}\"")
buildConfigField('long', 'CODE_TIMESTAMP', "${proj_code_time}L")
buildConfigField('String', 'COMMIT', proj_git ? "\"${proj_commit}\"" : "null")
buildConfigField('boolean', 'CLEAN_BUILD', "${proj_clean}")
+ buildConfigField('String', 'CODE_STORE', proj_store==""?"null":"\"${proj_store}\"")
+ buildConfigField('String', 'COMMIT_PATH', proj_commit_path==""?"null":"\"${proj_commit_path}\"")
}
diff --git a/gradle.properties b/gradle.properties
index 3db275d..ec523fe 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,7 +2,10 @@
MORNY_ARCHIVE_NAME = morny-coeur
-VERSION = 1.0.0-alpha3
+MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
+MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
+
+VERSION = 1.0.0-alpha4
USE_DELTA = false
VERSION_DELTA =
@@ -15,6 +18,6 @@ libSpotbugsVersion = 4.7.3
libMessivaVersion = 0.1.0.1
-libJavaTelegramBotApiVersion = 5.6.0
+libJavaTelegramBotApiVersion = 6.2.0
libJunitVersion = 5.9.0
diff --git a/src/main/java/cc/sukazyo/cono/morny/MornySystem.java b/src/main/java/cc/sukazyo/cono/morny/MornySystem.java
index a62290e..e15a81e 100644
--- a/src/main/java/cc/sukazyo/cono/morny/MornySystem.java
+++ b/src/main/java/cc/sukazyo/cono/morny/MornySystem.java
@@ -1,8 +1,10 @@
package cc.sukazyo.cono.morny;
+import cc.sukazyo.cono.morny.util.BuildConfigField;
import cc.sukazyo.cono.morny.util.FileUtils;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
@@ -13,20 +15,93 @@ import java.security.NoSuchAlgorithmException;
public class MornySystem {
/**
- * 程序的语义化版本号
- * 会由 gradle 任务 {@code updateVersionCode} 更新
+ * 程序的语义化版本号.
+ *
+ * 这个版本号是完整(verbose)构建的——它包含了以下的 {@link #VERSION_BASE}, {@link #VERSION_DELTA}, + * 和简写的 {@link BuildConfig#COMMIT} 字段. + * @since 1.0.0-alpha4 */ - public static final String VERSION = BuildConfig.VERSION; + @BuildConfigField @Nonnull public static final String VERSION = BuildConfig.VERSION; + /** + * 程序的基础版本号. + *
+ * 它只包含了版本号中的主要信息:例如 {@code 0.8.0.5}, {@code 1.0.0-alpha-3}, + * 而不会有用于精确定义的 {@link #VERSION_DELTA} 字段和作为附加使用的 {@link BuildConfig#COMMIT git commit 信息} + * @since 1.0.0-alpha4 + */ + @BuildConfigField @Nonnull public static final String VERSION_BASE = BuildConfig.VERSION_BASE; + /** + * 程序的版本 delta. + * —— 设计上用于在一个基版本当中分出不同构建的版本. + *
+ * {@link null} 作为值,表示这个字段没有被使用. + *
+ * 版本 delta 会以 {@code -δversion-delta} 的形式附着在 {@link #VERSION_BASE} 之后. + *
+ * 目前并不多被使用.
+ * @since 1.0.0-alpha4
+ */
+ @BuildConfigField @Nullable public static final String VERSION_DELTA = BuildConfig.VERSION_DELTA;
/**
- * Morny Coeur 当前的版本代号.
+ * Morny Coeur 当前的版本代号.
+ *
* 一个单个单词,一般作为一个大版本的名称,只在重大更新改变
* 格式保持为仅由小写字母和数字组成
* 有时也可能是复合词或特殊的词句
*
- * 会由 gradle 任务 {@code updateVersionCode} 更新
*/
- public static final String CODENAME = BuildConfig.CODENAME;
+ @BuildConfigField @Nonnull public static final String CODENAME = BuildConfig.CODENAME;
+
+ /**
+ * Coeur 的代码仓库的链接. 它应该链接到当前程序的源码主页.
+ *
+ * {@link null} 表示这个属性在构建时未被设置(或没有源码主页) + * @since 1.0.0-alpha4 + */ + @BuildConfigField @Nullable public static final String CODE_STORE = BuildConfig.CODE_STORE; + /** + * Coeur 的 git commit 链接. + *
+ * 它应该是一个可以通过 {@link String#format(String, Object...)} 要求格式的链接模板,带有一个 {@link String} 类型的槽位 ——
+ * 通过 String.format(COMMIT_PATH, {@link BuildConfig#COMMIT})
即可取得当前当前程序所基于的 commit 的链接。
+ * @since 1.0.0-alpha4
+ */
+ @BuildConfigField @Nullable public static final String COMMIT_PATH = BuildConfig.COMMIT_PATH;
+
+ /** @see #VERSION_DELTA */
+ @BuildConfigField
+ public static boolean isUseDelta () { return VERSION_DELTA != null; }
+
+ /** @see BuildConfig#COMMIT */
+ @BuildConfigField
+ @SuppressWarnings("ConstantConditions")
+ public static boolean isGitBuild () { return BuildConfig.COMMIT != null; }
+
+ /** @see BuildConfig#COMMIT */
+ @BuildConfigField
+ public static boolean isCleanBuild () { return BuildConfig.CLEAN_BUILD; }
+
+ /**
+ * 获取程序的当前构建所基于的 git commit 的链接.
+ *
+ * 如果 {@link #COMMIT_PATH}(一般表示没有公开储存库)
+ * 或是 {@link BuildConfig#COMMIT}(一般表示程序的构建环境没有使用 git)
+ * 任何一个不可用,则此方法也不可用。
+ *
+ * @return 当前构建的 git commit 链接,为空则表示不可用。
+ * @see #COMMIT_PATH
+ * @since 1.0.0-alpha4
+ */
+ @Nullable
+ @BuildConfigField
+ @SuppressWarnings("ConstantConditions")
+ public static String currentCodePath () {
+ if (COMMIT_PATH == null || !isGitBuild()) return null;
+ return String.format(COMMIT_PATH, BuildConfig.COMMIT);
+ }
+
+
/**
* 获取程序 jar 文件的 md5-hash 值
diff --git a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java
index 6c720f8..d7c4b3a 100644
--- a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java
+++ b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java
@@ -184,14 +184,24 @@ public class ServerMain {
logger.info(String.format("""
Morny Cono Version
- version :
- %s %s
+ Morny %s
+ %s%s
- md5hash :
%s
+ - gitstat :
+ %s
- co.time :
%d
%s [UTC]""",
- MornySystem.VERSION, MornySystem.CODENAME.toUpperCase(),
+ MornySystem.CODENAME.toUpperCase(),
+ MornySystem.VERSION_BASE,
+ MornySystem.isUseDelta() ? "-δ"+MornySystem.VERSION_DELTA : "",
MornySystem.getJarMd5(),
+ MornySystem.isGitBuild() ? (String.format(
+ "on commit %s\n %s",
+ MornySystem.isCleanBuild() ? "- clean-build" : "<δ/non-clean-build>",
+ BuildConfig.COMMIT
+ )) : "%s
- - %s
+ - %s
%s%s
core md5_hash:
- %s
coding timestamp:
- %d
- %s [UTC]
""",
escapeHtml(MornySystem.CODENAME.toUpperCase()),
- escapeHtml(MornySystem.VERSION),
+ escapeHtml(MornySystem.VERSION_BASE),
+ MornySystem.isUseDelta() ? String.format("-δ%s
", escapeHtml(Objects.requireNonNull(MornySystem.VERSION_DELTA))) : "",
+ MornySystem.isGitBuild()?"\n- git "+ (MornySystem.currentCodePath()==null ?
+ String.format("%s
", BuildConfig.COMMIT.substring(0, 8)) :
+ String.format("%s", MornySystem.currentCodePath(), BuildConfig.COMMIT.substring(0, 8))
+ ) + (MornySystem.isCleanBuild() ? "" : ".δ
") : "",
escapeHtml(MornySystem.getJarMd5()),
BuildConfig.CODE_TIMESTAMP,
escapeHtml(formatDate(BuildConfig.CODE_TIMESTAMP, 0))
@@ -255,17 +257,17 @@ public class MornyCommands {
).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML));
}
- private static class MornyRuntime implements ITelegramCommand {
+ private static class MornyRuntime implements ISimpleCommand {
@Nonnull @Override public String getName () { return "runtime"; }
@Nullable @Override public String[] getAliases () { return null; }
- @Nonnull @Override public String getParamRule () { return ""; }
- @Nonnull @Override public String getDescription () { return "获取 Bot 运行时信息(包括版本号)"; }
+ @Nonnull @Deprecated public String getParamRule () { return ""; }
+ @Nonnull @Deprecated public String getDescription () { return "获取 Bot 运行时信息(包括版本号)"; }
@Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandRuntimeExec(event); }
}
/**
* @since 0.4.1.2
*/
- private static void onCommandRuntimeExec (@Nonnull Update event) {
+ public static void onCommandRuntimeExec (@Nonnull Update event) {
String hostname;
try {
hostname = InetAddress.getLocalHost().getHostName();
@@ -286,7 +288,7 @@ public class MornyCommands {
- %d
/ %d
MB
- %d
cores
coeur version:
- - %s
(%s
)
+ - %s
%s%s*%s
- %s
- %s [UTC]
- [%d
]
@@ -307,8 +309,14 @@ public class MornyCommands {
Runtime.getRuntime().maxMemory() / 1024 / 1024,
Runtime.getRuntime().availableProcessors(),
// version
- escapeHtml(MornySystem.VERSION),
- escapeHtml(MornySystem.CODENAME),
+ escapeHtml(MornySystem.VERSION_BASE),
+ MornySystem.isUseDelta() ? String.format("-δ%s
", escapeHtml(Objects.requireNonNull(MornySystem.VERSION_DELTA))) : "",
+ MornySystem.isGitBuild()?String.format("-git.%s%s", MornySystem.currentCodePath()==null ? (
+ String.format("%s
", BuildConfig.COMMIT.substring(0, 8))
+ ) : (
+ String.format("%s", MornySystem.currentCodePath(), BuildConfig.COMMIT.substring(0, 8))
+ ), MornySystem.isCleanBuild()?"":".δ
"):"",
+ escapeHtml(MornySystem.CODENAME.toUpperCase()),
escapeHtml(MornySystem.getJarMd5()),
escapeHtml(formatDate(BuildConfig.CODE_TIMESTAMP, 0)),
BuildConfig.CODE_TIMESTAMP,
diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java
index 9d815bb..271f644 100644
--- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java
+++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyInformations.java
@@ -2,6 +2,7 @@ package cc.sukazyo.cono.morny.bot.command;
import cc.sukazyo.cono.morny.MornyCoeur;
import cc.sukazyo.cono.morny.data.TelegramStickers;
+import cc.sukazyo.cono.morny.util.tgapi.ExtraAction;
import cc.sukazyo.cono.morny.util.tgapi.InputCommand;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.SendSticker;
@@ -11,36 +12,97 @@ import javax.annotation.Nullable;
public class MornyInformations implements ITelegramCommand {
- private static final String ACT_STICKER = "stickers";
+ private static final String SUB_STICKER = "stickers";
+ private static final String SUB_RUNTIME = "runtime";
+ private static final String SUB_VERSION = "version";
+ private static final String SUB_VERSION_2 = "v";
@Nonnull @Override public String getName () { return "info"; }
@Nullable @Override public String[] getAliases () { return new String[0]; }
- @Nonnull @Override public String getParamRule () { return "[(stickers)|(stickers.)sticker_id]"; }
- @Nonnull @Override public String getDescription () { return "输出 Morny 当前版本的一些预定义信息"; }
+ @Nonnull @Override public String getParamRule () { return "[subcommand]"; }
+ @Nonnull @Override public String getDescription () { return "输出当前 Morny 的各种信息"; }
@Override
public void execute (@Nonnull InputCommand command, @Nonnull Update event) {
- if (!command.hasArgs() || command.getArgs().length > 1) {
- MornyCoeur.extra().exec(new SendSticker(event.message().chat().id(), TelegramStickers.ID_404).replyToMessageId(event.message().messageId()));
- }
+ if (!command.hasArgs()) echoRuntime(command, event);
final String action = command.getArgs()[0];
- if (action.startsWith("stickers")) {
- if (action.equals("stickers"))
- TelegramStickers.echoAllStickers(MornyCoeur.extra(), event.message().chat().id(), event.message().messageId());
- else {
- TelegramStickers.echoStickerByID(
- action.substring((ACT_STICKER+".").length()),
- MornyCoeur.extra(), event.message().chat().id(), event.message().messageId()
- );
- }
- return;
+ if (action.startsWith(SUB_STICKER)) {
+ echoStickers(command, event);
+ } else if (action.equals(SUB_RUNTIME)) {
+ echoRuntime(command, event);
+ } else if (action.equals(SUB_VERSION) || action.equals(SUB_VERSION_2)) {
+ echoVersion(command, event);
+ } else {
+ echo404(event);
}
- MornyCoeur.extra().exec(new SendSticker(event.message().chat().id(), TelegramStickers.ID_404).replyToMessageId(event.message().messageId()));
-
+ }
+
+ /**
+ * /info 子命令 {@value #SUB_STICKER}
+ */
+ public void echoStickers (@Nonnull InputCommand command, @Nonnull Update event) {
+ final long echoTo = event.message().chat().id();
+ final int replyToMessage = event.message().messageId();
+ String id = null;
+ if (command.getArgs()[0].equals(SUB_STICKER)) {
+ if (command.getArgs().length == 1) {
+ id = "";
+ } else if (command.getArgs().length == 2) {
+ id = command.getArgs()[1];
+ }
+ } else if (command.getArgs().length == 1) {
+ if (command.getArgs()[0].startsWith(SUB_STICKER+".") || command.getArgs()[0].startsWith(SUB_STICKER+"#")) {
+ id = command.getArgs()[0].substring(SUB_STICKER.length()+1);
+ }
+ }
+ if (id == null) { echo404(event); return; }
+ echoStickers(id, echoTo, replyToMessage);
+ }
+
+ /**
+ * 向 telegram 输出一个或全部 sticker
+ * @param id
+ * sticker 在 {@link TelegramStickers} 中的字段名。
+ * 使用 {@link ""}(空字符串)(不是{@link null}) 表示输出全部 sticker
+ * @param chatId 目标 chat id
+ * @param messageId 要回复的消息 id,特殊值跟随上游逻辑
+ * @see TelegramStickers#echoStickerByID(String, ExtraAction, long, int)
+ * @see TelegramStickers#echoAllStickers(ExtraAction, long, int)
+ */
+ public static void echoStickers (@Nonnull String id, long chatId, int messageId) {
+ if ("".equals(id)) TelegramStickers.echoAllStickers(MornyCoeur.extra(), chatId, messageId);
+ else TelegramStickers.echoStickerByID(id, MornyCoeur.extra(), chatId, messageId);
+ }
+
+ /**
+ * /info 子命令 {@value #SUB_RUNTIME}
+ * @since 1.0.0-alpha4
+ */
+ public static void echoRuntime (@Nonnull InputCommand command, @Nonnull Update event) {
+ if (command.getArgs().length == 1)
+ MornyCommands.onCommandRuntimeExec(event);
+ else echo404(event);
+ }
+
+ /**
+ * /info 子命令 {@value #SUB_VERSION}
+ * @since 1.0.0-alpha4
+ */
+ public static void echoVersion (@Nonnull InputCommand command, @Nonnull Update event) {
+ if (command.getArgs().length == 1)
+ MornyCommands.onCommandVersionExec(event);
+ else echo404(event);
+ }
+
+ private static void echo404 (@Nonnull Update event) {
+ MornyCoeur.extra().exec(new SendSticker(
+ event.message().chat().id(),
+ TelegramStickers.ID_404
+ ).replyToMessageId(event.message().messageId()));
}
}
diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java
index d02beae..0b362f9 100644
--- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java
+++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java
@@ -37,7 +37,7 @@ public class OnCallMsgSend extends EventListener {
) { }
@Override
- public boolean onMessage(Update update) {
+ public boolean onMessage(@Nonnull Update update) {
// 执行体检查
if (update.message().chat().type() != Chat.Type.Private) return false;
diff --git a/src/main/java/cc/sukazyo/cono/morny/data/TelegramStickers.java b/src/main/java/cc/sukazyo/cono/morny/data/TelegramStickers.java
index fb3f01c..d23d1fe 100644
--- a/src/main/java/cc/sukazyo/cono/morny/data/TelegramStickers.java
+++ b/src/main/java/cc/sukazyo/cono/morny/data/TelegramStickers.java
@@ -5,6 +5,7 @@ import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.request.SendSticker;
import com.pengrad.telegrambot.response.SendResponse;
+import javax.annotation.Nonnull;
import java.lang.reflect.Field;
/**
@@ -24,7 +25,14 @@ public class TelegramStickers {
public static final String ID_PROGYNOVA = "CAACAgUAAxkBAAICm2KEuL7UQqNP7vSPCg2DHJIND6UsAAKLAwACH4WSBszIo722aQ3jJAQ";
public static final String ID_NETWORK_ERR = "CAACAgEAAxkBAAID0WNJgNEkD726KW4vZeFlw0FlVVyNAAIXJgACePzGBb50o7O1RbxoKgQ";
- public static void echoAllStickers (ExtraAction actionObject, long sentChat, int replyToMessageId) {
+ /**
+ * 向 telegram 输出当前的 {@link TelegramStickers} 中的所有 stickers.
+ * @param actionObject 要使用的 telegram account 包装实例
+ * @param sentChat 目标 telegram chat id
+ * @param replyToMessageId 输出时回复指定的消息的 id。使用 {@link -1} 表示不回复消息
+ * @since 0.8.0.6
+ */
+ public static void echoAllStickers (@Nonnull ExtraAction actionObject, long sentChat, int replyToMessageId) {
for (Field object : TelegramStickers.class.getFields()) {
if (object.getType()==String.class && object.getName().startsWith("ID_")) {
@@ -45,7 +53,18 @@ public class TelegramStickers {
}
- public static void echoStickerByID (String stickerFieldID, ExtraAction actionObject, long sentChat, int replyToMessageId) {
+ /**
+ * 向 telegram 输出当前的 {@link TelegramStickers} 中的某个特定 sticker.
+ * @param stickerFieldID 要输出的 sticker 在 {@link TelegramStickers} 当中的字段名
+ * @param actionObject 要使用的 telegram account 包装实例
+ * @param sentChat 目标 telegram chat id
+ * @param replyToMessageId 输出时回复指定的消息的 id。使用 {@link -1} 表示不回复消息
+ * @since 0.8.0.6
+ */
+ public static void echoStickerByID (
+ @Nonnull String stickerFieldID,
+ @Nonnull ExtraAction actionObject, long sentChat, int replyToMessageId
+ ) {
try {
// normally get the sticker and echo
Field sticker = TelegramStickers.class.getField(stickerFieldID);
diff --git a/src/main/java/cc/sukazyo/cono/morny/util/BuildConfigField.java b/src/main/java/cc/sukazyo/cono/morny/util/BuildConfigField.java
new file mode 100644
index 0000000..c584a8b
--- /dev/null
+++ b/src/main/java/cc/sukazyo/cono/morny/util/BuildConfigField.java
@@ -0,0 +1,14 @@
+package cc.sukazyo.cono.morny.util;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * 这个注解表示当前字段是由 gradle 任务 {@code generateBuildConfig} 自动生成的.
+ * @since 1.0.0-alpha4
+ */
+@Documented
+@Target({ElementType.FIELD, ElementType.METHOD})
+public @interface BuildConfigField {}