diff --git a/gradle.properties b/gradle.properties index 78cc80d..68bfd0c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ ## Core -VERSION = 0.4.3.7 +VERSION = 0.5.0.0 # dependencies diff --git a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java index 91f2abf..b13d0d3 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.4.3.7"; - public static final long COMPILE_TIMESTAMP = 1642998030356L; + public static final String VERSION = "0.5.0.0"; + public static final long COMPILE_TIMESTAMP = 1643097522208L; } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/EventHack.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/EventHack.java similarity index 78% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/EventHack.java rename to src/main/java/cc/sukazyo/cono/morny/bot/command/EventHack.java index 36e2571..b43df8d 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/EventHack.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/EventHack.java @@ -1,4 +1,4 @@ -package cc.sukazyo.cono.morny.bot.event.on_commands; +package cc.sukazyo.cono.morny.bot.command; import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.MornyTrusted; @@ -9,11 +9,19 @@ import cc.sukazyo.untitled.util.telegram.object.InputCommand; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.request.SendSticker; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * {@link OnEventHackHandle} 的命令行前端 * @since 0.4.2.0 */ -public class EventHack { +public class EventHack implements ITelegramCommand { + + @Nonnull @Override public String getName () { return "/event_hack"; } + @Nullable @Override public String[] getAliases () { return null; } + @Nonnull @Override public String getParamRule () { return "[(user|group|any)]"; } + @Nonnull @Override public String getDescription () { return "输出 bot 下一个获取到的事件序列化数据"; } /** * {@link OnEventHackHandle} 的命令行前端
@@ -26,7 +34,8 @@ public class EventHack { * @param command 命令基础参数,解析出的命令对象 * @since 0.4.2.0 */ - public static void exec (Update event, InputCommand command) { + @Override + public void execute (@Nonnull InputCommand command, @Nonnull Update event) { boolean isOk = false; diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.java similarity index 81% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java rename to src/main/java/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.java index 24fb3df..e8bb9c8 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/GetUsernameAndId.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/GetUsernameAndId.java @@ -1,7 +1,8 @@ -package cc.sukazyo.cono.morny.bot.event.on_commands; +package cc.sukazyo.cono.morny.bot.command; import cc.sukazyo.cono.morny.MornyCoeur; +import cc.sukazyo.untitled.util.telegram.object.InputCommand; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.User; import com.pengrad.telegrambot.model.request.ParseMode; @@ -10,12 +11,21 @@ import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.response.GetChatMemberResponse; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; -public class GetUsernameAndId { +public class GetUsernameAndId implements ITelegramCommand { - public static void exec (@Nonnull String[] args, @Nonnull Update event) { + @Nonnull @Override public String getName () { return "/user"; } + @Nullable @Override public String[] getAliases () { return null; } + @Nonnull @Override public String getParamRule () { return "[userid]"; } + @Nonnull @Override public String getDescription () { return "获取指定或回复的用户相关信息"; } + + @Override + public void execute (@Nonnull InputCommand command, @Nonnull Update event) { + + final String[] args = command.getArgs(); if (args.length > 1) { MornyCoeur.extra().exec(new SendMessage( event.message().chat().id(), diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java new file mode 100644 index 0000000..75f6186 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java @@ -0,0 +1,23 @@ +package cc.sukazyo.cono.morny.bot.command; + +import cc.sukazyo.untitled.util.telegram.object.InputCommand; +import com.pengrad.telegrambot.model.Update; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface ITelegramCommand { + + @Nonnull + String getName(); + + @Nullable + String[] getAliases(); + @Nonnull + String getParamRule(); + @Nonnull + String getDescription(); + + void execute (@Nonnull InputCommand command, @Nonnull Update event); + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Ip186Query.java similarity index 63% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java rename to src/main/java/cc/sukazyo/cono/morny/bot/command/Ip186Query.java index 48c7f86..b66c6ae 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Ip186Query.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/Ip186Query.java @@ -1,4 +1,4 @@ -package cc.sukazyo.cono.morny.bot.event.on_commands; +package cc.sukazyo.cono.morny.bot.command; import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.data.ip186.IP186QueryResponse; @@ -7,8 +7,10 @@ import cc.sukazyo.cono.morny.data.ip186.IP186QueryHandler; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.request.SendMessage; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; @@ -18,7 +20,23 @@ import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; */ public class Ip186Query { - public static void exec (@Nonnull Update event, @Nonnull InputCommand command) { + public static class Ip implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/ip"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Nonnull @Override public String getParamRule () { return "[ip]"; } + @Nonnull @Override public String getDescription () { return "通过 https://ip.186526.xyz 查询 ip 资料"; } + @Override public void execute (@NotNull InputCommand command, @NotNull Update event) { exec(event, command); } + } + + public static class Whois implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/whois"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Nonnull @Override public String getParamRule () { return "[domain]"; } + @Nonnull @Override public String getDescription () { return "通过 https://ip.186526.xyz 查询域名资料"; } + @Override public void execute (@NotNull InputCommand command, @NotNull Update event) { exec(event, command); } + } + + private static void exec (@Nonnull Update event, @Nonnull InputCommand command) { String arg = null; if (!command.hasArgs()) { diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java similarity index 51% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java rename to src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java index 6196de1..198c6c9 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java @@ -1,81 +1,81 @@ -package cc.sukazyo.cono.morny.bot.event; +package cc.sukazyo.cono.morny.bot.command; import cc.sukazyo.cono.morny.GradleProjectConfigures; import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.MornySystem; -import cc.sukazyo.cono.morny.bot.api.EventListener; -import cc.sukazyo.cono.morny.bot.event.on_commands.EventHack; -import cc.sukazyo.cono.morny.bot.event.on_commands.GetUsernameAndId; -import cc.sukazyo.cono.morny.bot.event.on_commands.Ip186Query; -import cc.sukazyo.cono.morny.bot.event.on_commands.Nbnhhsh; 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.Update; import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.request.SendSticker; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import java.util.HashMap; +import java.util.Map; import static cc.sukazyo.cono.morny.Log.logger; import static cc.sukazyo.cono.morny.util.CommonFormatUtils.formatDate; import static cc.sukazyo.cono.morny.util.CommonFormatUtils.formatDuration; import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; -public class OnCommandExecute extends EventListener { +public class MornyCommands { - @Override - public boolean onMessage (@Nonnull Update event) { - if (event.message().text() == null) { - return false; // 检测到无消息文本,忽略掉命令处理 + private final Map commands = new HashMap<>(); + + private void pushCommandTo (@Nonnull String name, @Nonnull ITelegramCommand instance) { + if (commands.containsKey(name)) { + logger.warn(String.format(""" + Telegram command instance named "%s" already exists and will be override by another command instance + - current: %s + - new : %s""", + name, + commands.get(name).getClass().getName(), + instance.getClass().getName() + )); } - final InputCommand command = new InputCommand(event.message().text()); - if (command.getTarget() != null && !MornyCoeur.getUsername().equals(command.getTarget())) { - return true; // 检测到命令并非针对 morny,退出整个事件处理链 + commands.put(name, instance); + } + + public void register (@Nonnull ITelegramCommand... list) { + for (ITelegramCommand instance : list) { + final String[] aliases = instance.getAliases(); + pushCommandTo(instance.getName(), instance); + if (aliases!=null) for (String alias : aliases) pushCommandTo(alias, instance); } - switch (command.getCommand()) { - case "/user": - GetUsernameAndId.exec(command.getArgs(), event); - break; - case "/event_hack": - EventHack.exec(event, command); - break; - case "/o": - onCommandOnExec(event); - break; - case "/hi": - case "/hello": - onCommandHelloExec(event); - break; - case "/exit": - onCommandExitExec(event); - break; - case "/version": - onCommandVersionExec(event); - break; - case "/runtime": - onCommandRuntimeExec(event); - break; - case "/save": - onSaveDataExec(event); - break; - case "/jrrp": - onCommandJrrpExec(event); - break; - case "/ip": - case "/whois": - Ip186Query.exec(event, command); - break; - case "/nbnhhsh": - Nbnhhsh.exec(event, command); - break; - default: - return nonCommandExecutable(event, command); + } + + public MornyCommands () { + + register( + // simple commands register + new ON(), + new Hello(), + new Exit(), + new Version(), + new MornyRuntime(), + new Jrrp(), + new SaveData(), + // rich commands register + new EventHack(), + new GetUsernameAndId(), + new Ip186Query.Ip(), + new Ip186Query.Whois(), + new Nbnhhsh() + ); + + } + + public boolean execute (@Nonnull InputCommand command, @Nonnull Update event) { + if (commands.containsKey(command.getCommand())) { + commands.get(command.getCommand()).execute(command, event); + return true; } - return true; // 命令执行成功,标记事件为已处理,退出事件链 + return nonCommandExecutable(event, command); } private boolean nonCommandExecutable (Update event, InputCommand command) { @@ -90,15 +90,30 @@ public class OnCommandExecute extends EventListener { } } - private void onCommandOnExec (@Nonnull Update event) { + private static class ON implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/on"; } + @Nullable + @Override public String[] getAliases () { return null; } + @Nonnull @Override public String getParamRule () { return ""; } + @Nonnull @Override public String getDescription () { return "检查是否在线"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandOnExec(event); } + } + private static void onCommandOnExec (@Nonnull Update event) { MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_ONLINE_STATUS_RETURN + event.message().chat().id(), + TelegramStickers.ID_ONLINE_STATUS_RETURN ).replyToMessageId(event.message().messageId()) ); } - private void onCommandHelloExec (@Nonnull Update event) { + private static class Hello implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/hello"; } + @Nullable @Override public String[] getAliases () { return new String[]{"/hi"}; } + @Nonnull @Override public String getParamRule () { return ""; } + @Nonnull @Override public String getDescription () { return "打招呼"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandHelloExec(event); } + } + private static void onCommandHelloExec (@Nonnull Update event) { MornyCoeur.extra().exec(new SendSticker( event.message().chat().id(), TelegramStickers.ID_HELLO @@ -106,7 +121,14 @@ public class OnCommandExecute extends EventListener { ); } - private void onCommandExitExec (@Nonnull Update event) { + private static class Exit implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/exit"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Nonnull @Override public String getParamRule () { return ""; } + @Nonnull @Override public String getDescription () { return "关闭 Bot (仅可信成员)"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandExitExec(event); } + } + private static void onCommandExitExec (@Nonnull Update event) { if (MornyCoeur.trustedInstance().isTrusted(event.message().from().id())) { MornyCoeur.extra().exec(new SendSticker( event.message().chat().id(), @@ -125,7 +147,14 @@ public class OnCommandExecute extends EventListener { } } - private void onCommandVersionExec (@Nonnull Update event) { + private static class Version implements ITelegramCommand { + @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 版本信息"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandVersionExec(event); } + } + private static void onCommandVersionExec (@Nonnull Update event) { MornyCoeur.extra().exec(new SendMessage( event.message().chat().id(), String.format( @@ -145,10 +174,17 @@ public class OnCommandExecute extends EventListener { ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); } + private static class MornyRuntime implements ITelegramCommand { + @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 运行时信息(包括版本号)"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandRuntimeExec(event); } + } /** * @since 0.4.1.2 */ - private void onCommandRuntimeExec (@Nonnull Update event) { + private static void onCommandRuntimeExec (@Nonnull Update event) { MornyCoeur.extra().exec(new SendMessage( event.message().chat().id(), String.format(""" @@ -195,7 +231,14 @@ public class OnCommandExecute extends EventListener { ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); } - private void onCommandJrrpExec (Update event) { + private static class Jrrp implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/jrrp"; } + @Nullable @Override public String[] getAliases () { return null; } + @Nonnull @Override public String getParamRule () { return ""; } + @Nonnull @Override public String getDescription () { return "获取 (假的) jrrp"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onCommandJrrpExec(event); } + } + private static void onCommandJrrpExec (Update event) { final double jrrp = MornyJrrp.getJrrpFromTelegramUser(event.message().from(), System.currentTimeMillis()); final String endChar = jrrp>70 ? "!" : jrrp>30 ? ";" : "..."; MornyCoeur.extra().exec(new SendMessage( @@ -208,10 +251,17 @@ public class OnCommandExecute extends EventListener { ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); } + private static class SaveData implements ITelegramCommand { + @Nonnull @Override public String getName () { return "/save"; } + @Nullable @Override public String[] getAliases () { return null; } + @Nonnull @Override public String getParamRule () { return ""; } + @Nonnull @Override public String getDescription () { return "保存缓存数据到文件(仅可信成员)"; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { onSaveDataExec(event); } + } /** * @since 0.4.3.0 */ - private void onSaveDataExec (Update event) { + private static void onSaveDataExec (Update event) { if (MornyCoeur.trustedInstance().isTrusted(event.message().from().id())) { logger.info("called save from command by " + TGToString.as(event.message().from()).toStringLogTag()); MornyCoeur.callSaveData(); @@ -229,5 +279,5 @@ public class OnCommandExecute extends EventListener { logger.info("403 call save tag from user " + TGToString.as(event.message().from()).toStringLogTag()); } } - + } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Nbnhhsh.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.java similarity index 79% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Nbnhhsh.java rename to src/main/java/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.java index 7dd130e..b72127d 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Nbnhhsh.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/Nbnhhsh.java @@ -1,4 +1,4 @@ -package cc.sukazyo.cono.morny.bot.event.on_commands; +package cc.sukazyo.cono.morny.bot.command; import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.ParseMode; @@ -9,11 +9,20 @@ import cc.sukazyo.cono.morny.data.NbnhhshQuery; import cc.sukazyo.untitled.util.string.StringArrays; import cc.sukazyo.untitled.util.telegram.object.InputCommand; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; -public class Nbnhhsh { +public class Nbnhhsh implements ITelegramCommand { - public static void exec (Update event, InputCommand command) { + @Nonnull @Override public String getName () { return "/nbnhhsh"; } + @Nullable @Override public String[] getAliases () { return null; } + @Nonnull @Override public String getParamRule () { return "[text]"; } + @Nonnull @Override public String getDescription () { return "检索文本内 nbnhhsh 词条"; } + + @Override + public void execute (@Nonnull InputCommand command, @Nonnull Update event) { try { diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/Roll.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/Roll.java new file mode 100644 index 0000000..c3c865f --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/Roll.java @@ -0,0 +1,4 @@ +package cc.sukazyo.cono.morny.bot.command; + +public class Roll { +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java index 716b99d..6d1d64d 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/EventListeners.java @@ -4,7 +4,7 @@ import cc.sukazyo.cono.morny.bot.api.EventListenerManager; public class EventListeners { - public static final OnCommandExecute COMMANDS_LISTENER = new OnCommandExecute(); + public static final OnTelegramCommand COMMANDS_LISTENER = new OnTelegramCommand(); public static final OnActivityRecord ACTIVITY_RECORDER = new OnActivityRecord(); public static final OnUserSlashAction USER_SLASH_ACTION = new OnUserSlashAction(); public static final OnUpdateTimestampOffsetLock UPDATE_TIMESTAMP_OFFSET_LOCK = new OnUpdateTimestampOffsetLock(); 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 new file mode 100644 index 0000000..2b971ed --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java @@ -0,0 +1,28 @@ +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; + +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) { + return false; // 检测到无消息文本,忽略掉命令处理 + } + final InputCommand command = new InputCommand(event.message().text()); + if (command.getTarget() != null && !MornyCoeur.getUsername().equals(command.getTarget())) { + return true; // 检测到命令并非针对 morny,退出整个事件处理链 + } + return commandManager.execute(command, event); // 转交命令管理器执行命令 + } + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Roll.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Roll.java deleted file mode 100644 index 4cb209a..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/on_commands/Roll.java +++ /dev/null @@ -1,4 +0,0 @@ -package cc.sukazyo.cono.morny.bot.event.on_commands; - -public class Roll { -}