diff --git a/README.md b/README.md new file mode 100644 index 0000000..996713e --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +[book]: https://book.sukazyo.cc/morny +[tg-account]: https://t.me/morny_cono_annie_bot +[issues]: https://github.com/Eyre-S/Coeur-Morny-Cono/issues +[todo]: https://github.com/users/Eyre-S/projects/1 +[artifact]: https://mvn.sukazyo.cc/main/cc/sukazyo/morny-coeur + +[tg4j]: https://github.com/pengrad/java-telegram-bot-api +[spotbugs]: https://spotbugs.github.io/ +[junit5]: https://junit.org/junit5/ + +
+ +# ~~给所有喜欢morny的大家的~~ Morny Coeur 源代码 + +![social preview card](morny-github-social-preview-card@0.75x.png) + +一个 telegram 上的服侍 A.C.Sukazyo Eyre 和它的花宫成员的 bot 的内核源 + +[Task Listing][todo] | [~~BBS~~][issues] | [Published][artifact] + +[说明书][book] | [FindInTelegram][tg-account] + +
+ +--- + +
+ +### Libraries Used + +[Java Telegram Bot API][tg4j] + +[SpotBugs Annotations][spotbugs] | [JUnit 5][junit5] + +
diff --git a/gradle.properties b/gradle.properties index 78cc80d..6df2753 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ ## Core -VERSION = 0.4.3.7 +VERSION = 0.5.0.6 # dependencies diff --git a/morny-github-social-preview-card@0.75x.png b/morny-github-social-preview-card@0.75x.png new file mode 100644 index 0000000..30bf201 Binary files /dev/null and b/morny-github-social-preview-card@0.75x.png differ diff --git a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java index 91f2abf..f48072a 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.6"; + public static final long COMPILE_TIMESTAMP = 1644378359640L; } diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java b/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java index b745d2d..2a7d03c 100644 --- a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java +++ b/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java @@ -1,11 +1,14 @@ 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.bot.query.MornyQueries; 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 +27,14 @@ public class MornyCoeur { /** 当前 Morny 的{@link MornyTrusted 信任验证机}实例 */ private final MornyTrusted trusted; + /** 当前 Morny 的 telegram 命令管理器 */ + private final MornyCommands commandManager = new MornyCommands(); + private final MornyQueries queryManager = new MornyQueries(); /** morny 的 bot 账户 */ private final TelegramBot account; private final ExtraAction extraActionInstance; + private final boolean isRemoveCommandListWhenExit; /** * morny 的 bot 账户的用户名
*
@@ -67,10 +74,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); @@ -79,7 +88,7 @@ public class MornyCoeur { } try { - final LogInResult loginResult = login(botKey); + final LogInResult loginResult = login(botKey, botUsername); this.account = loginResult.account; this.username = loginResult.username; this.trusted = new MornyTrusted(master, trustedChat); @@ -113,14 +122,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; } @@ -139,15 +158,20 @@ public class MornyCoeur { * 用于退出时进行缓存的任务处理等进行安全退出 */ private void exitCleanup () { + logger.info("clean:save tracker data."); 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")); } /** @@ -161,15 +185,15 @@ public class MornyCoeur { * @return 成功登录后的 {@link TelegramBot} 对象 */ @Nonnull - private LogInResult login (@Nonnull String key) { + private static LogInResult login (@Nonnull String key, @Nullable String requireName) { final TelegramBot account = new TelegramBot(key); logger.info("Trying to login..."); for (int i = 1; i < 4; i++) { if (i != 1) logger.info("retrying..."); try { final String username = account.execute(new GetMe()).user().username(); - if (this.username != null && !this.username.equals(username)) - throw new RuntimeException("Required the bot @" + this.username + " but @" + username + " logged in!"); + if (requireName != null && !requireName.equals(username)) + throw new RuntimeException("Required the bot @" + requireName + " but @" + username + " logged in!"); logger.info("Succeed login to @" + username); return new LogInResult(account, username); } catch (Exception e) { @@ -229,6 +253,16 @@ public class MornyCoeur { return INSTANCE.trusted; } + @Nonnull + public static MornyCommands commandManager () { + return INSTANCE.commandManager; + } + + @Nonnull + public static MornyQueries queryManager () { + return INSTANCE.queryManager; + } + @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..b7d9d78 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,17 +120,14 @@ public class ServerMain { trustedChat = Long.parseLong(args[i]); continue; } - } - - } else { - - if (key == null) { - key = args[i]; - continue; - } - if (username == null) { - username = args[i]; - continue; + case "--auto-cmd-list", "-ca" -> { + autoCmdList = true; + continue; + } + case "--auto-cmd-remove", "-cr" -> { + autoCmdRemove = true; + continue; + } } } @@ -154,8 +159,16 @@ public class ServerMain { if (showWelcome) logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII); if (welcomeEchoMode) return; - assert key != null; - MornyCoeur.main(key, username, master, trustedChat, outdatedBlock?System.currentTimeMillis():0); + if (key == null) { + logger.info("Parameter required has no value:\n --token."); + return; + } + MornyCoeur.main( + key, username, + master, trustedChat, + outdatedBlock?System.currentTimeMillis():0, + autoCmdList, autoCmdRemove + ); } 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 54% 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..f7d136f 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.cono.morny.util.TelegramUserInformation; +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,19 @@ 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(), @@ -53,59 +61,9 @@ public class GetUsernameAndId { final User user = response.chatMember().user(); - final StringBuilder userInformation = new StringBuilder(); - userInformation.append(String.format( - """ - userid : - - %d""", - userId - )); - if (user.username() == null) { - userInformation.append("\nusername : null"); - } else { - userInformation.append(String.format( - """ - - username : - - %s""", - escapeHtml(user.username()) - )); - } - if (user.firstName() == null) { - userInformation.append("\nfirstname : null"); - } else { - userInformation.append(String.format( - """ - - firstname : - - %s""", - escapeHtml(user.firstName()) - )); - } - if (user.lastName() == null) { - userInformation.append("\nlastname : null"); - } else { - userInformation.append(String.format( - """ - - lastname : - - %s""", - escapeHtml(user.lastName()) - )); - } - if (user.languageCode() != null) { - userInformation.append(String.format( - """ - - language-code : - - %s""", - escapeHtml(user.languageCode()) - )); - } - MornyCoeur.extra().exec(new SendMessage( event.message().chat().id(), - userInformation.toString() + TelegramUserInformation.informationOutputHTML(user) ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java new file mode 100644 index 0000000..0f3fea2 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/ISimpleCommand.java @@ -0,0 +1,19 @@ +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 ISimpleCommand { + + @Nonnull + String getName(); + + @Nullable + String[] getAliases(); + + void execute (@Nonnull InputCommand command, @Nonnull Update event); + +} 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..b090a95 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/ITelegramCommand.java @@ -0,0 +1,12 @@ +package cc.sukazyo.cono.morny.bot.command; + +import javax.annotation.Nonnull; + +public interface ITelegramCommand extends ISimpleCommand { + + @Nonnull + String getParamRule(); + @Nonnull + String getDescription(); + +} 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 61% 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..7a47390 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()) { @@ -45,7 +63,7 @@ public class Ip186Query { try { IP186QueryResponse response = switch (command.getCommand()) { case "/ip" -> IP186QueryHandler.queryIp(arg); - case "/whois" -> IP186QueryHandler.queryWhois(arg); + case "/whois" -> IP186QueryHandler.queryWhoisPretty(arg); default -> throw new IllegalArgumentException("Unknown 186-IP query method " + command.getCommand()); }; MornyCoeur.extra().exec(new SendMessage( 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 new file mode 100644 index 0000000..d2fc28b --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/MornyCommands.java @@ -0,0 +1,335 @@ +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.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.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +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 MornyCommands { + + private final Map commands = new LinkedHashMap<>(); + + private void pushCommandTo (@Nonnull String name, @Nonnull ISimpleCommand 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() + )); + } + commands.put(name, instance); + } + + public void register (@Nonnull ISimpleCommand... list) { + for (ISimpleCommand instance : list) { + final String[] aliases = instance.getAliases(); + pushCommandTo(instance.getName(), instance); + if (aliases!=null) for (String alias : aliases) pushCommandTo(alias, instance); + } + } + + public MornyCommands () { + + register( + new ON(), + new Hello(), + new GetUsernameAndId(), + new EventHack(), + new Nbnhhsh(), + new Ip186Query.Ip(), + new Ip186Query.Whois(), + new SaveData(), + new Version(), + new MornyRuntime(), + new Jrrp(), + new Exit() + ); + + // 统一注册这些奇怪的东西&.& + register( + new 喵呜.抱抱(), + new 喵呜.揉揉(), + new 喵呜.蹭蹭(), + new 喵呜.贴贴() + ); + + } + + public boolean execute (@Nonnull InputCommand command, @Nonnull Update event) { + if (commands.containsKey(command.getCommand())) { + commands.get(command.getCommand()).execute(command, event); + return true; + } + 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 (command instanceof ITelegramCommand && regKey.equals(command.getName())) { + telegramFormatListing.add(formatTelegramCommandListLine( + command.getName(), + ((ITelegramCommand)command).getParamRule(), + ((ITelegramCommand)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 { // 无法解析的显式命令格式,报错找不到命令 + MornyCoeur.extra().exec(new SendSticker( + event.message().chat().id(), + TelegramStickers.ID_404 + ).replyToMessageId(event.message().messageId()) + ); + return true; + } + } + + /// /// /// /// /// /// /// /// /// + /// + /// Old Simple Command Block + /// + + 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 + ).replyToMessageId(event.message().messageId()) + ); + } + + 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 + ).replyToMessageId(event.message().messageId()) + ); + } + + 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(), + TelegramStickers.ID_EXIT + ).replyToMessageId(event.message().messageId()) + ); + logger.info("Morny exited by user " + TGToString.as(event.message().from()).toStringLogTag()); + System.exit(0); + } else { + MornyCoeur.extra().exec(new SendSticker( + event.message().chat().id(), + TelegramStickers.ID_403 + ).replyToMessageId(event.message().messageId()) + ); + logger.info("403 exited tag from user " + TGToString.as(event.message().from()).toStringLogTag()); + } + } + + 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( + """ + version: + - %s + core md5_hash: + - %s + compile timestamp: + - %d + - %s [UTC]""", + escapeHtml(MornySystem.VERSION), + escapeHtml(MornySystem.getJarMd5()), + GradleProjectConfigures.COMPILE_TIMESTAMP, + escapeHtml(formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0)) + ) + ).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 static void onCommandRuntimeExec (@Nonnull Update event) { + MornyCoeur.extra().exec(new SendMessage( + event.message().chat().id(), + String.format(""" + system: + - %s + - %s + - %d cores + java runtime: + - %s + - %s + vm memory: + - %d / %d MB + morny version: + - %s + - %s + - %s [UTC] + - [%d] + continuous: + - %s + - [%d] + - %s [UTC] + - [%d]""", + // system + escapeHtml(System.getProperty("os.name")), + escapeHtml(System.getProperty("os.version")), + Runtime.getRuntime().availableProcessors(), + // java + escapeHtml(System.getProperty("java.vm.name")), + escapeHtml(System.getProperty("java.version")), + // memory + Runtime.getRuntime().totalMemory() / 1024 / 1024, + Runtime.getRuntime().maxMemory() / 1024 / 1024, + // version + escapeHtml(MornySystem.VERSION), + escapeHtml(MornySystem.getJarMd5()), + escapeHtml(formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0)), + GradleProjectConfigures.COMPILE_TIMESTAMP, + // continuous + escapeHtml(formatDuration(System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp)), + System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp, + escapeHtml(formatDate(MornyCoeur.coeurStartTimestamp, 0)), + MornyCoeur.coeurStartTimestamp + ) + ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); + } + + 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( + event.message().chat().id(), + String.format( + "%s 在(utc的)今天的运气指数是———— %.2f%% %s", + TGToString.as(event.message().from()).fullnameRefHtml(), + jrrp, escapeHtml(endChar) + ) + ).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 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(); + MornyCoeur.extra().exec(new SendSticker( + event.message().chat().id(), + TelegramStickers.ID_SAVED + ).replyToMessageId(event.message().messageId()) + ); + } else { + MornyCoeur.extra().exec(new SendSticker( + event.message().chat().id(), + TelegramStickers.ID_403 + ).replyToMessageId(event.message().messageId()) + ); + 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/command/喵呜.java b/src/main/java/cc/sukazyo/cono/morny/bot/command/喵呜.java new file mode 100644 index 0000000..ca31006 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/command/喵呜.java @@ -0,0 +1,59 @@ +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.request.ParseMode; +import com.pengrad.telegrambot.request.SendMessage; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +@SuppressWarnings("NonAsciiCharacters") +public class 喵呜 { + + public static class 抱抱 implements ISimpleCommand { + @Nonnull @Override public String getName () { return "/抱抱"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { + MornyCoeur.extra().exec(new SendMessage( + event.message().chat().id(), + "抱抱——" + )); + } + } + + public static class 揉揉 implements ISimpleCommand { + @Nonnull @Override public String getName () { return "/揉揉"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { + MornyCoeur.extra().exec(new SendMessage( + event.message().chat().id(), + "蹭蹭w" + )); + } + } + + public static class 蹭蹭 implements ISimpleCommand { + @Nonnull @Override public String getName () { return "/蹭蹭"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { + MornyCoeur.extra().exec(new SendMessage( + event.message().chat().id(), + "喵呜~-" + )); + } + } + + public static class 贴贴 implements ISimpleCommand { + @Nonnull @Override public String getName () { return "/贴贴"; } + @Nullable @Override public String[] getAliases () { return new String[0]; } + @Override public void execute (@Nonnull InputCommand command, @Nonnull Update event) { + MornyCoeur.extra().exec(new SendMessage( + event.message().chat().id(), + "(贴贴喵呜&.&)" + ).parseMode(ParseMode.HTML)); + } + } + +} 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..3920a57 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,11 +4,11 @@ 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(); - public static final OnInlineQuery INLINE_QUERY = new OnInlineQuery(); + public static final OnInlineQueries INLINE_QUERY = new OnInlineQueries(); public static final OnCallMe CALL_ME = new OnCallMe(); public static final OnEventHackHandle EVENT_HACK_HANDLE = new OnEventHackHandle(); diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java deleted file mode 100644 index 6196de1..0000000 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java +++ /dev/null @@ -1,233 +0,0 @@ -package cc.sukazyo.cono.morny.bot.event; - -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 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 { - - @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,退出整个事件处理链 - } - 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); - } - return true; // 命令执行成功,标记事件为已处理,退出事件链 - } - - private boolean nonCommandExecutable (Update event, InputCommand command) { - if (command.getTarget() == null) return false; // 无法解析的命令,转交事件链后代处理 - else { // 无法解析的显式命令格式,报错找不到命令 - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_404 - ).replyToMessageId(event.message().messageId()) - ); - return true; - } - } - - private void onCommandOnExec (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_ONLINE_STATUS_RETURN - ).replyToMessageId(event.message().messageId()) - ); - } - - private void onCommandHelloExec (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_HELLO - ).replyToMessageId(event.message().messageId()) - ); - } - - private void onCommandExitExec (@Nonnull Update event) { - if (MornyCoeur.trustedInstance().isTrusted(event.message().from().id())) { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_EXIT - ).replyToMessageId(event.message().messageId()) - ); - logger.info("Morny exited by user " + TGToString.as(event.message().from()).toStringLogTag()); - System.exit(0); - } else { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_403 - ).replyToMessageId(event.message().messageId()) - ); - logger.info("403 exited tag from user " + TGToString.as(event.message().from()).toStringLogTag()); - } - } - - private void onCommandVersionExec (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - String.format( - """ - version: - - %s - core md5_hash: - - %s - compile timestamp: - - %d - - %s [UTC]""", - escapeHtml(MornySystem.VERSION), - escapeHtml(MornySystem.getJarMd5()), - GradleProjectConfigures.COMPILE_TIMESTAMP, - escapeHtml(formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0)) - ) - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - } - - /** - * @since 0.4.1.2 - */ - private void onCommandRuntimeExec (@Nonnull Update event) { - MornyCoeur.extra().exec(new SendMessage( - event.message().chat().id(), - String.format(""" - system: - - %s - - %s - - %d cores - java runtime: - - %s - - %s - vm memory: - - %d / %d MB - morny version: - - %s - - %s - - %s [UTC] - - [%d] - continuous: - - %s - - [%d] - - %s [UTC] - - [%d]""", - // system - escapeHtml(System.getProperty("os.name")), - escapeHtml(System.getProperty("os.version")), - Runtime.getRuntime().availableProcessors(), - // java - escapeHtml(System.getProperty("java.vm.name")), - escapeHtml(System.getProperty("java.version")), - // memory - Runtime.getRuntime().totalMemory() / 1024 / 1024, - Runtime.getRuntime().maxMemory() / 1024 / 1024, - // version - escapeHtml(MornySystem.VERSION), - escapeHtml(MornySystem.getJarMd5()), - escapeHtml(formatDate(GradleProjectConfigures.COMPILE_TIMESTAMP, 0)), - GradleProjectConfigures.COMPILE_TIMESTAMP, - // continuous - escapeHtml(formatDuration(System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp)), - System.currentTimeMillis() - MornyCoeur.coeurStartTimestamp, - escapeHtml(formatDate(MornyCoeur.coeurStartTimestamp, 0)), - MornyCoeur.coeurStartTimestamp - ) - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - } - - private 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( - event.message().chat().id(), - String.format( - "%s 在(utc的)今天的运气指数是———— %.2f%% %s", - TGToString.as(event.message().from()).fullnameRefHtml(), - jrrp, escapeHtml(endChar) - ) - ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); - } - - /** - * @since 0.4.3.0 - */ - private 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(); - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_SAVED - ).replyToMessageId(event.message().messageId()) - ); - } else { - MornyCoeur.extra().exec(new SendSticker( - event.message().chat().id(), - TelegramStickers.ID_403 - ).replyToMessageId(event.message().messageId()) - ); - 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/OnInlineQuery.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQueries.java similarity index 50% rename from src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQuery.java rename to src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQueries.java index 5a64be5..4e113c8 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQuery.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnInlineQueries.java @@ -2,14 +2,12 @@ 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.util.EncryptUtils; import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; -import com.pengrad.telegrambot.model.request.InputTextMessageContent; -import com.pengrad.telegrambot.model.request.ParseMode; +import com.pengrad.telegrambot.model.request.InlineQueryResult; import com.pengrad.telegrambot.request.AnswerInlineQuery; import javax.annotation.Nonnull; +import java.util.List; /** * telegram inlineQuery 功能的处理类, @@ -17,21 +15,21 @@ import javax.annotation.Nonnull; * * @since 0.4.1.3 */ -public class OnInlineQuery extends EventListener { +public class OnInlineQueries extends EventListener { /** * @since 0.4.1.3 */ @Override public boolean onInlineQuery (@Nonnull Update update) { - MornyCoeur.extra().exec(new AnswerInlineQuery(update.inlineQuery().id(), new InlineQueryResultArticle[]{ - new InlineQueryResultArticle( - EncryptUtils.encryptByMD5(update.inlineQuery().query()), - "Raw Input", - new InputTextMessageContent(update.inlineQuery().query()).parseMode(ParseMode.MarkdownV2) - ) - })); + + List> results = MornyCoeur.queryManager().query(update); + + if (results.size() == 0) return false; + + MornyCoeur.extra().exec(new AnswerInlineQuery(update.inlineQuery().id(), results.toArray(InlineQueryResult[]::new))); return true; + } } 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..e0f2419 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnTelegramCommand.java @@ -0,0 +1,25 @@ +package cc.sukazyo.cono.morny.bot.event; + +import cc.sukazyo.cono.morny.MornyCoeur; +import cc.sukazyo.cono.morny.bot.api.EventListener; +import cc.sukazyo.untitled.util.telegram.object.InputCommand; + +import com.pengrad.telegrambot.model.Update; + +import javax.annotation.Nonnull; + +public class OnTelegramCommand extends EventListener { + + @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 MornyCoeur.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 { -} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.java new file mode 100644 index 0000000..6f1d0da --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/query/ITelegramQuery.java @@ -0,0 +1,13 @@ +package cc.sukazyo.cono.morny.bot.query; + +import javax.annotation.Nullable; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.InlineQueryResult; + +public interface ITelegramQuery > { + + @Nullable + T query (Update event); + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/MornyQueries.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/MornyQueries.java new file mode 100644 index 0000000..8bbbd30 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/query/MornyQueries.java @@ -0,0 +1,29 @@ +package cc.sukazyo.cono.morny.bot.query; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.InlineQueryResult; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; + +public class MornyQueries { + + private final List> queryInstances = new ArrayList<>(); + + public MornyQueries () { + queryInstances.add(new RawText()); + queryInstances.add(new MyInformation()); + } + + @Nonnull + public List> query (@Nonnull Update event) { + final List> results = new ArrayList<>(); + for (ITelegramQuery instance : queryInstances) { + final InlineQueryResult r = instance.query(event); + if (r!=null) results.add(r); + } + return results; + } + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/MyInformation.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/MyInformation.java new file mode 100644 index 0000000..0140b6f --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/query/MyInformation.java @@ -0,0 +1,26 @@ +package cc.sukazyo.cono.morny.bot.query; + +import javax.annotation.Nullable; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; +import com.pengrad.telegrambot.model.request.InputTextMessageContent; +import com.pengrad.telegrambot.model.request.ParseMode; + +import cc.sukazyo.cono.morny.util.TelegramUserInformation; + +public class MyInformation implements ITelegramQuery { + + public static final String ID_PREFIX = "[morny/info/me]"; + public static final String TITLE = "My Account Information"; + + @Override + @Nullable + public InlineQueryResultArticle query(Update event) { + if (!(event.inlineQuery().query() == null || "".equals(event.inlineQuery().query()))) return null; + return new InlineQueryResultArticle(ID_PREFIX, TITLE, new InputTextMessageContent( + TelegramUserInformation.informationOutputHTML(event.inlineQuery().from()) + ).parseMode(ParseMode.HTML)); + } + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/query/RawText.java b/src/main/java/cc/sukazyo/cono/morny/bot/query/RawText.java new file mode 100644 index 0000000..2e3cceb --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/query/RawText.java @@ -0,0 +1,27 @@ +package cc.sukazyo.cono.morny.bot.query; + +import cc.sukazyo.cono.morny.util.EncryptUtils; + +import javax.annotation.Nullable; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; +import com.pengrad.telegrambot.model.request.InputTextMessageContent; + +public class RawText implements ITelegramQuery { + + public static final String ID_PREFIX = "[morny/r/text]"; + public static final String TITLE = "Raw Text"; + + @Override + @Nullable + public InlineQueryResultArticle query (Update event) { + if (event.inlineQuery().query() == null || "".equals(event.inlineQuery().query())) return null; + return new InlineQueryResultArticle( + ID_PREFIX + EncryptUtils.encryptByMD5(event.inlineQuery().query()), + TITLE, + new InputTextMessageContent(event.inlineQuery().query()) + ); + } + +} diff --git a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java b/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java index c29d0b9..0f60d81 100644 --- a/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java +++ b/src/main/java/cc/sukazyo/cono/morny/data/ip186/IP186QueryHandler.java @@ -62,6 +62,20 @@ public class IP186QueryHandler { return commonQuery(requestUrl, QUERY_WHOIS_PARAM); } + /** + * 将 {@link #queryWhois(String)} 的结果进行裁剪. + *
    + * 将会删除返回内容中 {@code >>> XXX <<<} 行以后的注释串, + * 以达到只保留重要信息的目的。 + * + * @see #queryWhois(String) + */ + @Nonnull + public static IP186QueryResponse queryWhoisPretty (String domain) throws IOException { + final IP186QueryResponse raw = queryWhois(domain); + return new IP186QueryResponse(raw.url(), raw.body().substring(0, raw.body().indexOf("<<<")+3)); + } + @Nonnull private static IP186QueryResponse commonQuery (String requestUrl, String queryIpParam) throws IOException { Request request = new Request.Builder().url(requestUrl + "?" + queryIpParam).build(); diff --git a/src/main/java/cc/sukazyo/cono/morny/data/tracker/TrackerDataManager.java b/src/main/java/cc/sukazyo/cono/morny/data/tracker/TrackerDataManager.java index 06945ab..7b2372f 100644 --- a/src/main/java/cc/sukazyo/cono/morny/data/tracker/TrackerDataManager.java +++ b/src/main/java/cc/sukazyo/cono/morny/data/tracker/TrackerDataManager.java @@ -43,7 +43,7 @@ public class TrackerDataManager { logger.info("CALLED TO EXIT! writing cache."); } if (record.size() != 0) { - save(reset()); + save(); } else logger.info("nothing to do yet"); } while (!postProcess); diff --git a/src/main/java/cc/sukazyo/cono/morny/util/TelegramUserInformation.java b/src/main/java/cc/sukazyo/cono/morny/util/TelegramUserInformation.java new file mode 100644 index 0000000..011e4da --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/util/TelegramUserInformation.java @@ -0,0 +1,64 @@ +package cc.sukazyo.cono.morny.util; + +import com.pengrad.telegrambot.model.User; + +import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; +public class TelegramUserInformation { + + public static String informationOutputHTML (User user) { + + final StringBuilder userInformation = new StringBuilder(); + userInformation.append(String.format( + """ + userid : + - %d""", + user.id() + )); + if (user.username() == null) { + userInformation.append("\nusername : null"); + } else { + userInformation.append(String.format( + """ + + username : + - %s""", + escapeHtml(user.username()) + )); + } + if (user.firstName() == null) { + userInformation.append("\nfirstname : null"); + } else { + userInformation.append(String.format( + """ + + firstname : + - %s""", + escapeHtml(user.firstName()) + )); + } + if (user.lastName() == null) { + userInformation.append("\nlastname : null"); + } else { + userInformation.append(String.format( + """ + + lastname : + - %s""", + escapeHtml(user.lastName()) + )); + } + if (user.languageCode() != null) { + userInformation.append(String.format( + """ + + language-code : + - %s""", + escapeHtml(user.languageCode()) + )); + } + + return userInformation.toString(); + + } + +}