diff --git a/gradle.properties b/gradle.properties index 68bfd0c..c5f6335 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ ## Core -VERSION = 0.5.0.0 +VERSION = 0.5.0.1 # dependencies diff --git a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java index b13d0d3..0ce77cb 100644 --- a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java +++ b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java @@ -4,6 +4,6 @@ package cc.sukazyo.cono.morny; * the final field that will be updated by gradle automatically. */ public class GradleProjectConfigures { - public static final String VERSION = "0.5.0.0"; - public static final long COMPILE_TIMESTAMP = 1643097522208L; + public static final String VERSION = "0.5.0.1"; + public static final long COMPILE_TIMESTAMP = 1643447337882L; } diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java b/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java index b745d2d..50b0ef2 100644 --- a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java +++ b/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java @@ -1,11 +1,13 @@ package cc.sukazyo.cono.morny; import cc.sukazyo.cono.morny.bot.api.OnUpdate; +import cc.sukazyo.cono.morny.bot.command.MornyCommands; import cc.sukazyo.cono.morny.bot.event.EventListeners; import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager; import cc.sukazyo.untitled.telegram.api.extra.ExtraAction; import com.pengrad.telegrambot.TelegramBot; +import com.pengrad.telegrambot.model.DeleteMyCommands; import com.pengrad.telegrambot.request.GetMe; import javax.annotation.Nonnull; @@ -24,10 +26,13 @@ public class MornyCoeur { /** 当前 Morny 的{@link MornyTrusted 信任验证机}实例 */ private final MornyTrusted trusted; + /** 当前 Morny 的 telegram 命令管理器 */ + private final MornyCommands commandManager = new MornyCommands(); /** morny 的 bot 账户 */ private final TelegramBot account; private final ExtraAction extraActionInstance; + private final boolean isRemoveCommandListWhenExit; /** * morny 的 bot 账户的用户名
*
@@ -67,10 +72,12 @@ public class MornyCoeur { */ private MornyCoeur ( @Nonnull String botKey, @Nullable String botUsername, - long master, long trustedChat, long latestEventTimestamp + long master, long trustedChat, long latestEventTimestamp, + boolean isRemoveCommandListWhenExit ) { this.latestEventTimestamp = latestEventTimestamp; + this.isRemoveCommandListWhenExit = isRemoveCommandListWhenExit; configureSafeExit(); logger.info("args key:\n " + botKey); @@ -113,14 +120,24 @@ public class MornyCoeur { */ public static void main ( @Nonnull String botKey, @Nullable String botUsername, - long master, long trustedChat, long latestEventTimestamp + long master, long trustedChat, long latestEventTimestamp, + boolean isAutomaticResetCommandList, boolean isRemoveCommandListWhenExit ) { if (INSTANCE == null) { logger.info("System Starting"); - INSTANCE = new MornyCoeur(botKey, botUsername, master, trustedChat, latestEventTimestamp); + INSTANCE = new MornyCoeur( + botKey, botUsername, + master, trustedChat, + latestEventTimestamp, + isRemoveCommandListWhenExit + ); TrackerDataManager.init(); EventListeners.registerAllListeners(); INSTANCE.account.setUpdatesListener(OnUpdate::onNormalUpdate); + if (isAutomaticResetCommandList) { + logger.info("resetting telegram command list"); + commandManager().automaticUpdateList(); + } logger.info("System start complete"); return; } @@ -141,13 +158,17 @@ public class MornyCoeur { private void exitCleanup () { TrackerDataManager.DAEMON.interrupt(); TrackerDataManager.trackingLock.lock(); + if (isRemoveCommandListWhenExit) { + extra().exec(new DeleteMyCommands()); + logger.info("cleaned up command list."); + } } /** * 为程序在虚拟机上添加退出钩子 */ private void configureSafeExit () { - Runtime.getRuntime().addShutdownHook(new Thread(this::exitCleanup)); + Runtime.getRuntime().addShutdownHook(new Thread(this::exitCleanup, "Exit-Cleaning")); } /** @@ -229,6 +250,11 @@ public class MornyCoeur { return INSTANCE.trusted; } + @Nonnull + public static MornyCommands commandManager () { + return INSTANCE.commandManager; + } + @Nonnull public static ExtraAction extra () { return INSTANCE.extraActionInstance; diff --git a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java index fcbe489..09590b9 100644 --- a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java +++ b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java @@ -49,6 +49,12 @@ public class ServerMain { * {@code --outdated-block} 会使得 {@link MornyCoeur#latestEventTimestamp} * 赋值为程序启动的时间,从而造成阻挡程序启动之前的消息事件处理效果。 * + *
  • + * {@code --auto-cmd-list} 使 morny 在启动时自动依据程序本体更新登录 bot 的命令列表 + *
  • + *
  • + * {@code --auto-cmd-remove} 使 morny 在关闭时自动依据程序本体删除 bot 的命令列表 + *
  • * * 除去选项之外,第一个参数会被赋值为 bot 的 telegram bot api token, * 第二个参数会被赋值为 bot 的 username 限定名。其余的参数会被认定为无法理解。
    @@ -59,7 +65,7 @@ public class ServerMain { * 但实际上这并不影响现在的使用,选项赋值目前仍属于测试功能
    * 但请勿混用,这将使两个赋值出现混淆并产生不可知的结果 * - * @see MornyCoeur#main(String, String, long, long, long) + * @see MornyCoeur#main * @since 0.4.0.0 * @param args 参数组 */ @@ -70,25 +76,27 @@ public class ServerMain { boolean outdatedBlock = false; long master = 793274677L; long trustedChat = -1001541451710L; + boolean autoCmdList = false; + boolean autoCmdRemove = false; for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { switch (args[i]) { - case "--outdated-block" -> { + case "--outdated-block", "-ob" -> { outdatedBlock = true; continue; } - case "--no-hello" -> { + case "--no-hello", "-hf" -> { showWelcome = false; continue; } - case "--only-hello" -> { + case "--only-hello", "-o" -> { welcomeEchoMode = true; continue; } - case "--version" -> { + case "--version", "-v" -> { versionEchoMode = true; continue; } @@ -112,6 +120,14 @@ public class ServerMain { trustedChat = Long.parseLong(args[i]); continue; } + case "--auto-cmd-list", "-ca" -> { + autoCmdList = true; + continue; + } + case "--auto-cmd-remove", "-cr" -> { + autoCmdRemove = true; + continue; + } } } else { @@ -155,7 +171,12 @@ public class ServerMain { if (welcomeEchoMode) return; assert key != null; - MornyCoeur.main(key, username, master, trustedChat, outdatedBlock?System.currentTimeMillis():0); + MornyCoeur.main( + key, username, + master, trustedChat, + outdatedBlock?System.currentTimeMillis():0, + autoCmdList, autoCmdRemove + ); } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java index 198c6c9..19f3078 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java @@ -7,15 +7,19 @@ import cc.sukazyo.cono.morny.data.MornyJrrp; import cc.sukazyo.cono.morny.data.TelegramStickers; import cc.sukazyo.untitled.telegram.api.formatting.TGToString; import cc.sukazyo.untitled.util.telegram.object.InputCommand; +import com.pengrad.telegrambot.model.BotCommand; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.request.SendSticker; +import com.pengrad.telegrambot.request.SetMyCommands; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import static cc.sukazyo.cono.morny.Log.logger; @@ -25,7 +29,7 @@ import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; public class MornyCommands { - private final Map commands = new HashMap<>(); + private final Map commands = new LinkedHashMap<>(); private void pushCommandTo (@Nonnull String name, @Nonnull ITelegramCommand instance) { if (commands.containsKey(name)) { @@ -52,20 +56,18 @@ public class MornyCommands { public MornyCommands () { register( - // simple commands register new ON(), new Hello(), - new Exit(), + new GetUsernameAndId(), + new EventHack(), + new Nbnhhsh(), + new Ip186Query.Ip(), + new Ip186Query.Whois(), + new SaveData(), new Version(), new MornyRuntime(), new Jrrp(), - new SaveData(), - // rich commands register - new EventHack(), - new GetUsernameAndId(), - new Ip186Query.Ip(), - new Ip186Query.Whois(), - new Nbnhhsh() + new Exit() ); } @@ -78,6 +80,43 @@ public class MornyCommands { return nonCommandExecutable(event, command); } + public void automaticUpdateList () { + BotCommand[] commandList = getCommandListTelegram(); + MornyCoeur.extra().exec(new SetMyCommands( + commandList + )); + logger.info("automatic updated telegram command list :\n" + commandListToString(commandList)); + } + + private String commandListToString (@Nonnull BotCommand[] list) { + StringBuilder builder = new StringBuilder(); + for (BotCommand signal : list) { + builder.append(signal.command()).append(" - ").append(signal.description()).append("\n"); + } + return builder.substring(0, builder.length()-1); + } + + public BotCommand[] getCommandListTelegram () { + final List telegramFormatListing = new ArrayList<>(); + commands.forEach((regKey, command) -> { + if (regKey.equals(command.getName())) { + telegramFormatListing.add(formatTelegramCommandListLine( + command.getName(), + command.getParamRule(), + command.getDescription() + )); + if (command.getAliases() != null) for (String alias : command.getAliases()) { + telegramFormatListing.add(formatTelegramCommandListLine(alias, "", "↑")); + } + } + }); + return telegramFormatListing.toArray(BotCommand[]::new); + } + + private BotCommand formatTelegramCommandListLine (@Nonnull String commandName, @Nonnull String paramRule, @Nonnull String intro) { + return new BotCommand(commandName, "".equals(paramRule) ? (intro) : (paramRule+" - "+intro)); + } + private boolean nonCommandExecutable (Update event, InputCommand command) { if (command.getTarget() == null) return false; // 无法解析的命令,转交事件链后代处理 else { // 无法解析的显式命令格式,报错找不到命令 @@ -90,6 +129,11 @@ public class MornyCommands { } } + /// /// /// /// /// /// /// /// /// + /// + /// Old Simple Command Block + /// + private static class ON implements ITelegramCommand { @Nonnull @Override public String getName () { return "/on"; } @Nullable diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java index 2b971ed..e0f2419 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java @@ -2,7 +2,6 @@ package cc.sukazyo.cono.morny.bot.event; import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.bot.api.EventListener; -import cc.sukazyo.cono.morny.bot.command.MornyCommands; import cc.sukazyo.untitled.util.telegram.object.InputCommand; import com.pengrad.telegrambot.model.Update; @@ -11,8 +10,6 @@ import javax.annotation.Nonnull; public class OnTelegramCommand extends EventListener { - private final MornyCommands commandManager = new MornyCommands(); - @Override public boolean onMessage (@Nonnull Update event) { if (event.message().text() == null) { @@ -22,7 +19,7 @@ public class OnTelegramCommand extends EventListener { if (command.getTarget() != null && !MornyCoeur.getUsername().equals(command.getTarget())) { return true; // 检测到命令并非针对 morny,退出整个事件处理链 } - return commandManager.execute(command, event); // 转交命令管理器执行命令 + return MornyCoeur.commandManager().execute(command, event); // 转交命令管理器执行命令 } }