添加项目 git 链接相关配置,大改动版本显示方式,/version 与 /runtime 合并进 /info

- 将 /version 和 /runtime 合并为了 /info 的子命令
  - 旧的 /version 和 /runtime 命令仍然可用
  - runtime 现在是 /info 的无参数行为
- 更新了各种位置的版本显示方式
  - /version 现在通过组装的方式显示版本号的 BASE 与 DELTA 部分,并支持了可能的 git commit 显示,同时支持输出 commit 链接
  - /runtime 现在通过组装的方式显示版本号的 BASE, DELTA, GIT 部分,其中也支持了 git commit 链接,同时 CODENAME 的显示方式规范为了 `version*CODENAME` 的格式
  - ServerMain 的 -v 修改了显示格式,同时添加了 gitstat 字段显示 build 时的 git 信息
  - ServerMain 的启动版本回显(仍使用完全体VERSION)将 md5hash 和 code-time 移到了新行
- dependencies update
  - java-telegram-bot-api: 5.6.0 -> 6.2.0
This commit is contained in:
A.C.Sukazyo Eyre 2022-11-09 01:41:01 +08:00
parent d8eb372063
commit 201c8bcd1a
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
9 changed files with 249 additions and 52 deletions

View File

@ -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}\"")
}

View File

@ -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

View File

@ -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 {
/**
* 程序的语义化版本号<br>
* 会由 gradle 任务 {@code updateVersionCode} 更新
* 程序的语义化版本号.
* <p>
* 这个版本号是完整(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;
/**
* 程序的基础版本号.
* <p>
* 它只包含了版本号中的主要信息例如 {@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.
* 设计上用于在一个基版本当中分出不同构建的版本.
* <p>
* {@link null} 作为值表示这个字段没有被使用.
* <p>
* 版本 delta 会以 {@code -δversion-delta} 的形式附着在 {@link #VERSION_BASE} 之后.
* <p>
* <small>目前并不多被使用.</small>
* @since 1.0.0-alpha4
*/
@BuildConfigField @Nullable public static final String VERSION_DELTA = BuildConfig.VERSION_DELTA;
/**
* Morny Coeur 当前的版本代号.<br>
* Morny Coeur 当前的版本代号.
* <p>
* 一个单个单词一般作为一个大版本的名称只在重大更新改变<br>
* 格式保持为仅由小写字母和数字组成<br>
* 有时也可能是复合词或特殊的词句<br>
* <br>
* 会由 gradle 任务 {@code updateVersionCode} 更新
*/
public static final String CODENAME = BuildConfig.CODENAME;
@BuildConfigField @Nonnull public static final String CODENAME = BuildConfig.CODENAME;
/**
* Coeur 的代码仓库的链接. 它应该链接到当前程序的源码主页.
* <p>
* {@link null} 表示这个属性在构建时未被设置或没有源码主页
* @since 1.0.0-alpha4
*/
@BuildConfigField @Nullable public static final String CODE_STORE = BuildConfig.CODE_STORE;
/**
* Coeur git commit 链接.
* <p>
* 它应该是一个可以通过 {@link String#format(String, Object...)} 要求格式的链接模板带有一个 {@link String} 类型的槽位
* 通过 <code>String.format(COMMIT_PATH, {@link BuildConfig#COMMIT})</code> 即可取得当前当前程序所基于的 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 的链接.
* <p>
* 如果 {@link #COMMIT_PATH}<small>一般表示没有公开储存库</small>
* 或是 {@link BuildConfig#COMMIT}<small>一般表示程序的构建环境没有使用 git</small>
* 任何一个不可用则此方法也不可用
*
* @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 <br>

View File

@ -184,14 +184,24 @@ public class ServerMain {
logger.info(String.format("""
Morny Cono Version
- version :
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
)) : "<non-git-build>",
BuildConfig.CODE_TIMESTAMP,
CommonFormat.formatDate(BuildConfig.CODE_TIMESTAMP, 0)
));
@ -204,11 +214,12 @@ public class ServerMain {
logger.info(String.format("""
ServerMain.java Loaded >>>
- version %s (%s)(%d)
- Morny %s""",
- version %s
- Morny %s
- <%s> [%d]""",
MornySystem.VERSION,
MornySystem.getJarMd5(), BuildConfig.CODE_TIMESTAMP,
MornySystem.CODENAME.toUpperCase()
MornySystem.CODENAME.toUpperCase(),
MornySystem.getJarMd5(), BuildConfig.CODE_TIMESTAMP
));
//#

View File

@ -21,10 +21,7 @@ import javax.annotation.Nullable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import static cc.sukazyo.cono.morny.Log.logger;
import static cc.sukazyo.cono.morny.util.CommonFormat.formatDate;
@ -226,28 +223,33 @@ public class MornyCommands {
}
}
private static class Version implements ITelegramCommand {
private static class Version implements ISimpleCommand {
@Nonnull @Override public String getName () { return "version"; }
@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) { onCommandVersionExec(event); }
}
private static void onCommandVersionExec (@Nonnull Update event) {
public static void onCommandVersionExec (@Nonnull Update event) {
MornyCoeur.extra().exec(new SendMessage(
event.message().chat().id(),
String.format(
"""
version:
- Morny <code>%s</code>
- <code>%s</code>
- <code>%s</code>%s%s
core md5_hash:
- <code>%s</code>
coding timestamp:
- <code>%d</code>
- <code>%s [UTC]</code>""",
escapeHtml(MornySystem.CODENAME.toUpperCase()),
escapeHtml(MornySystem.VERSION),
escapeHtml(MornySystem.VERSION_BASE),
MornySystem.isUseDelta() ? String.format("-δ<code>%s</code>", escapeHtml(Objects.requireNonNull(MornySystem.VERSION_DELTA))) : "",
MornySystem.isGitBuild()?"\n- git "+ (MornySystem.currentCodePath()==null ?
String.format("<code>%s</code>", BuildConfig.COMMIT.substring(0, 8)) :
String.format("<a href='%s'>%s</a>", MornySystem.currentCodePath(), BuildConfig.COMMIT.substring(0, 8))
) + (MornySystem.isCleanBuild() ? "" : ".<code>δ</code>") : "",
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 {
- <code>%d</code> / <code>%d</code> MB
- <code>%d</code> cores
coeur version:
- <code>%s</code> (<code>%s</code>)
- <code>%s</code>%s%s*<code>%s</code>
- <code>%s</code>
- <code>%s [UTC]</code>
- [<code>%d</code>]
@ -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("-δ<code>%s</code>", escapeHtml(Objects.requireNonNull(MornySystem.VERSION_DELTA))) : "",
MornySystem.isGitBuild()?String.format("-git.%s%s", MornySystem.currentCodePath()==null ? (
String.format("<code>%s</code>", BuildConfig.COMMIT.substring(0, 8))
) : (
String.format("<a href='%s'>%s</a>", MornySystem.currentCodePath(), BuildConfig.COMMIT.substring(0, 8))
), MornySystem.isCleanBuild()?"":".<code>δ</code>"):"",
escapeHtml(MornySystem.CODENAME.toUpperCase()),
escapeHtml(MornySystem.getJarMd5()),
escapeHtml(formatDate(BuildConfig.CODE_TIMESTAMP, 0)),
BuildConfig.CODE_TIMESTAMP,

View File

@ -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;
}
MornyCoeur.extra().exec(new SendSticker(event.message().chat().id(), TelegramStickers.ID_404).replyToMessageId(event.message().messageId()));
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);
}
}
/**
* /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()));
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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 {}