[[[release 0.5.0.6]]]

## 📇功能

- 添加了 [inline][li-me] 版本的 /user 目前只支持获取自己的信息
- 添加 [「喵呜」][cm-meow] 系列...命令...?

## 🔌系统接口

- 正式删除了被弃用的 key 和 username 的参数直赋
- 添加自动向 Telegram 同步与清理命令列表的功能
  - 添加了启动选项 --auto-cmd-list 控制同步行为
  - 添加了启动选项 --auto-cmd-remove 控制清理行为
- 为现在已有的启动行为控制类选项添加了其简写形式
- 添加 TelegramCommand 抽象层与管理类
- 添加了 InlineQuery 抽象层与管理器

## 🔩技术修改/typo

- 关闭 raw 输出 在查询字符串为空时的触发
- 删除显示 186 whois 查询 查询结果的 >>> xxx <<< 后的注释信息
This commit is contained in:
A.C.Sukazyo Eyre 2022-03-15 17:40:56 +08:00
commit f0821ac492
Signed by: Eyre_S
GPG Key ID: EFB47D98FE082FAD
27 changed files with 811 additions and 347 deletions

35
README.md Normal file
View File

@ -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/
<div align=center>
# ~~给所有喜欢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]
<br>
---
<br>
### Libraries Used
[Java Telegram Bot API][tg4j]
[SpotBugs Annotations][spotbugs] | [JUnit 5][junit5]
</div>

View File

@ -1,6 +1,6 @@
## Core ## Core
VERSION = 0.4.3.7 VERSION = 0.5.0.6
# dependencies # dependencies

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -4,6 +4,6 @@ package cc.sukazyo.cono.morny;
* the final field that will be updated by gradle automatically. * the final field that will be updated by gradle automatically.
*/ */
public class GradleProjectConfigures { public class GradleProjectConfigures {
public static final String VERSION = "0.4.3.7"; public static final String VERSION = "0.5.0.6";
public static final long COMPILE_TIMESTAMP = 1642998030356L; public static final long COMPILE_TIMESTAMP = 1644378359640L;
} }

View File

@ -1,11 +1,14 @@
package cc.sukazyo.cono.morny; package cc.sukazyo.cono.morny;
import cc.sukazyo.cono.morny.bot.api.OnUpdate; 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.event.EventListeners;
import cc.sukazyo.cono.morny.bot.query.MornyQueries;
import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager; import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager;
import cc.sukazyo.untitled.telegram.api.extra.ExtraAction; import cc.sukazyo.untitled.telegram.api.extra.ExtraAction;
import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.model.DeleteMyCommands;
import com.pengrad.telegrambot.request.GetMe; import com.pengrad.telegrambot.request.GetMe;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -24,10 +27,14 @@ public class MornyCoeur {
/** 当前 Morny 的{@link MornyTrusted 信任验证机}实例 */ /** 当前 Morny 的{@link MornyTrusted 信任验证机}实例 */
private final MornyTrusted trusted; private final MornyTrusted trusted;
/** 当前 Morny 的 telegram 命令管理器 */
private final MornyCommands commandManager = new MornyCommands();
private final MornyQueries queryManager = new MornyQueries();
/** morny 的 bot 账户 */ /** morny 的 bot 账户 */
private final TelegramBot account; private final TelegramBot account;
private final ExtraAction extraActionInstance; private final ExtraAction extraActionInstance;
private final boolean isRemoveCommandListWhenExit;
/** /**
* morny bot 账户的用户名<br> * morny bot 账户的用户名<br>
* <br> * <br>
@ -67,10 +74,12 @@ public class MornyCoeur {
*/ */
private MornyCoeur ( private MornyCoeur (
@Nonnull String botKey, @Nullable String botUsername, @Nonnull String botKey, @Nullable String botUsername,
long master, long trustedChat, long latestEventTimestamp long master, long trustedChat, long latestEventTimestamp,
boolean isRemoveCommandListWhenExit
) { ) {
this.latestEventTimestamp = latestEventTimestamp; this.latestEventTimestamp = latestEventTimestamp;
this.isRemoveCommandListWhenExit = isRemoveCommandListWhenExit;
configureSafeExit(); configureSafeExit();
logger.info("args key:\n " + botKey); logger.info("args key:\n " + botKey);
@ -79,7 +88,7 @@ public class MornyCoeur {
} }
try { try {
final LogInResult loginResult = login(botKey); final LogInResult loginResult = login(botKey, botUsername);
this.account = loginResult.account; this.account = loginResult.account;
this.username = loginResult.username; this.username = loginResult.username;
this.trusted = new MornyTrusted(master, trustedChat); this.trusted = new MornyTrusted(master, trustedChat);
@ -113,14 +122,24 @@ public class MornyCoeur {
*/ */
public static void main ( public static void main (
@Nonnull String botKey, @Nullable String botUsername, @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) { if (INSTANCE == null) {
logger.info("System Starting"); logger.info("System Starting");
INSTANCE = new MornyCoeur(botKey, botUsername, master, trustedChat, latestEventTimestamp); INSTANCE = new MornyCoeur(
botKey, botUsername,
master, trustedChat,
latestEventTimestamp,
isRemoveCommandListWhenExit
);
TrackerDataManager.init(); TrackerDataManager.init();
EventListeners.registerAllListeners(); EventListeners.registerAllListeners();
INSTANCE.account.setUpdatesListener(OnUpdate::onNormalUpdate); INSTANCE.account.setUpdatesListener(OnUpdate::onNormalUpdate);
if (isAutomaticResetCommandList) {
logger.info("resetting telegram command list");
commandManager().automaticUpdateList();
}
logger.info("System start complete"); logger.info("System start complete");
return; return;
} }
@ -139,15 +158,20 @@ public class MornyCoeur {
* 用于退出时进行缓存的任务处理等进行安全退出 * 用于退出时进行缓存的任务处理等进行安全退出
*/ */
private void exitCleanup () { private void exitCleanup () {
logger.info("clean:save tracker data.");
TrackerDataManager.DAEMON.interrupt(); TrackerDataManager.DAEMON.interrupt();
TrackerDataManager.trackingLock.lock(); TrackerDataManager.trackingLock.lock();
if (isRemoveCommandListWhenExit) {
extra().exec(new DeleteMyCommands());
logger.info("cleaned up command list.");
}
} }
/** /**
* 为程序在虚拟机上添加退出钩子 * 为程序在虚拟机上添加退出钩子
*/ */
private void configureSafeExit () { 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} 对象 * @return 成功登录后的 {@link TelegramBot} 对象
*/ */
@Nonnull @Nonnull
private LogInResult login (@Nonnull String key) { private static LogInResult login (@Nonnull String key, @Nullable String requireName) {
final TelegramBot account = new TelegramBot(key); final TelegramBot account = new TelegramBot(key);
logger.info("Trying to login..."); logger.info("Trying to login...");
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++) {
if (i != 1) logger.info("retrying..."); if (i != 1) logger.info("retrying...");
try { try {
final String username = account.execute(new GetMe()).user().username(); final String username = account.execute(new GetMe()).user().username();
if (this.username != null && !this.username.equals(username)) if (requireName != null && !requireName.equals(username))
throw new RuntimeException("Required the bot @" + this.username + " but @" + username + " logged in!"); throw new RuntimeException("Required the bot @" + requireName + " but @" + username + " logged in!");
logger.info("Succeed login to @" + username); logger.info("Succeed login to @" + username);
return new LogInResult(account, username); return new LogInResult(account, username);
} catch (Exception e) { } catch (Exception e) {
@ -229,6 +253,16 @@ public class MornyCoeur {
return INSTANCE.trusted; return INSTANCE.trusted;
} }
@Nonnull
public static MornyCommands commandManager () {
return INSTANCE.commandManager;
}
@Nonnull
public static MornyQueries queryManager () {
return INSTANCE.queryManager;
}
@Nonnull @Nonnull
public static ExtraAction extra () { public static ExtraAction extra () {
return INSTANCE.extraActionInstance; return INSTANCE.extraActionInstance;

View File

@ -49,6 +49,12 @@ public class ServerMain {
* {@code --outdated-block} 会使得 {@link MornyCoeur#latestEventTimestamp} * {@code --outdated-block} 会使得 {@link MornyCoeur#latestEventTimestamp}
* 赋值为程序启动的时间从而造成阻挡程序启动之前的消息事件处理效果 * 赋值为程序启动的时间从而造成阻挡程序启动之前的消息事件处理效果
* </li> * </li>
* <li>
* {@code --auto-cmd-list} 使 morny 在启动时自动依据程序本体更新登录 bot 的命令列表
* </li>
* <li>
* {@code --auto-cmd-remove} 使 morny 在关闭时自动依据程序本体删除 bot 的命令列表
* </li>
* </ul> * </ul>
* 除去选项之外第一个参数会被赋值为 bot telegram bot api token * 除去选项之外第一个参数会被赋值为 bot telegram bot api token
* 第二个参数会被赋值为 bot username 限定名其余的参数会被认定为无法理解<br> * 第二个参数会被赋值为 bot username 限定名其余的参数会被认定为无法理解<br>
@ -59,7 +65,7 @@ public class ServerMain {
* <s>但实际上这并不影响现在的使用选项赋值目前仍属于测试功能</s><br> * <s>但实际上这并不影响现在的使用选项赋值目前仍属于测试功能</s><br>
* <b>但请勿混用</b>这将使两个赋值出现混淆并<b>产生不可知的结果</b> * <b>但请勿混用</b>这将使两个赋值出现混淆并<b>产生不可知的结果</b>
* *
* @see MornyCoeur#main(String, String, long, long, long) * @see MornyCoeur#main
* @since 0.4.0.0 * @since 0.4.0.0
* @param args 参数组 * @param args 参数组
*/ */
@ -70,25 +76,27 @@ public class ServerMain {
boolean outdatedBlock = false; boolean outdatedBlock = false;
long master = 793274677L; long master = 793274677L;
long trustedChat = -1001541451710L; long trustedChat = -1001541451710L;
boolean autoCmdList = false;
boolean autoCmdRemove = false;
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) { if (args[i].startsWith("-")) {
switch (args[i]) { switch (args[i]) {
case "--outdated-block" -> { case "--outdated-block", "-ob" -> {
outdatedBlock = true; outdatedBlock = true;
continue; continue;
} }
case "--no-hello" -> { case "--no-hello", "-hf" -> {
showWelcome = false; showWelcome = false;
continue; continue;
} }
case "--only-hello" -> { case "--only-hello", "-o" -> {
welcomeEchoMode = true; welcomeEchoMode = true;
continue; continue;
} }
case "--version" -> { case "--version", "-v" -> {
versionEchoMode = true; versionEchoMode = true;
continue; continue;
} }
@ -112,17 +120,14 @@ public class ServerMain {
trustedChat = Long.parseLong(args[i]); trustedChat = Long.parseLong(args[i]);
continue; continue;
} }
} case "--auto-cmd-list", "-ca" -> {
autoCmdList = true;
} else { continue;
}
if (key == null) { case "--auto-cmd-remove", "-cr" -> {
key = args[i]; autoCmdRemove = true;
continue; continue;
} }
if (username == null) {
username = args[i];
continue;
} }
} }
@ -154,8 +159,16 @@ public class ServerMain {
if (showWelcome) logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII); if (showWelcome) logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII);
if (welcomeEchoMode) return; if (welcomeEchoMode) return;
assert key != null; if (key == null) {
MornyCoeur.main(key, username, master, trustedChat, outdatedBlock?System.currentTimeMillis():0); logger.info("Parameter required has no value:\n --token.");
return;
}
MornyCoeur.main(
key, username,
master, trustedChat,
outdatedBlock?System.currentTimeMillis():0,
autoCmdList, autoCmdRemove
);
} }

View File

@ -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.MornyCoeur;
import cc.sukazyo.cono.morny.MornyTrusted; 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.model.Update;
import com.pengrad.telegrambot.request.SendSticker; import com.pengrad.telegrambot.request.SendSticker;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* {@link OnEventHackHandle} 的命令行前端 * {@link OnEventHackHandle} 的命令行前端
* @since 0.4.2.0 * @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} 的命令行前端<br> * {@link OnEventHackHandle} 的命令行前端<br>
@ -26,7 +34,8 @@ public class EventHack {
* @param command 命令基础参数解析出的命令对象 * @param command 命令基础参数解析出的命令对象
* @since 0.4.2.0 * @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; boolean isOk = false;

View File

@ -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.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.Update;
import com.pengrad.telegrambot.model.User; import com.pengrad.telegrambot.model.User;
import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.model.request.ParseMode;
@ -10,12 +11,19 @@ import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.response.GetChatMemberResponse; import com.pengrad.telegrambot.response.GetChatMemberResponse;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; public class GetUsernameAndId implements ITelegramCommand {
public class GetUsernameAndId { @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 "获取指定或回复的用户相关信息"; }
public static void exec (@Nonnull String[] args, @Nonnull Update event) { @Override
public void execute (@Nonnull InputCommand command, @Nonnull Update event) {
final String[] args = command.getArgs();
if (args.length > 1) { MornyCoeur.extra().exec(new SendMessage( if (args.length > 1) { MornyCoeur.extra().exec(new SendMessage(
event.message().chat().id(), event.message().chat().id(),
@ -53,59 +61,9 @@ public class GetUsernameAndId {
final User user = response.chatMember().user(); final User user = response.chatMember().user();
final StringBuilder userInformation = new StringBuilder();
userInformation.append(String.format(
"""
userid :
- <code>%d</code>""",
userId
));
if (user.username() == null) {
userInformation.append("\nusername : <u>null</u>");
} else {
userInformation.append(String.format(
"""
username :
- <code>%s</code>""",
escapeHtml(user.username())
));
}
if (user.firstName() == null) {
userInformation.append("\nfirstname : <u>null</u>");
} else {
userInformation.append(String.format(
"""
firstname :
- <code>%s</code>""",
escapeHtml(user.firstName())
));
}
if (user.lastName() == null) {
userInformation.append("\nlastname : <u>null</u>");
} else {
userInformation.append(String.format(
"""
lastname :
- <code>%s</code>""",
escapeHtml(user.lastName())
));
}
if (user.languageCode() != null) {
userInformation.append(String.format(
"""
language-code :
- <code>%s</code>""",
escapeHtml(user.languageCode())
));
}
MornyCoeur.extra().exec(new SendMessage( MornyCoeur.extra().exec(new SendMessage(
event.message().chat().id(), event.message().chat().id(),
userInformation.toString() TelegramUserInformation.informationOutputHTML(user)
).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML)); ).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML));
} }

View File

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

View File

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

View File

@ -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.MornyCoeur;
import cc.sukazyo.cono.morny.data.ip186.IP186QueryResponse; 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.Update;
import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.model.request.ParseMode;
import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.request.SendMessage;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; 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 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; String arg = null;
if (!command.hasArgs()) { if (!command.hasArgs()) {
@ -45,7 +63,7 @@ public class Ip186Query {
try { try {
IP186QueryResponse response = switch (command.getCommand()) { IP186QueryResponse response = switch (command.getCommand()) {
case "/ip" -> IP186QueryHandler.queryIp(arg); 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()); default -> throw new IllegalArgumentException("Unknown 186-IP query method " + command.getCommand());
}; };
MornyCoeur.extra().exec(new SendMessage( MornyCoeur.extra().exec(new SendMessage(

View File

@ -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<String, ISimpleCommand> 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<BotCommand> 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:
- <code>%s</code>
core md5_hash:
- <code>%s</code>
compile timestamp:
- <code>%d</code>
- <code>%s [UTC]</code>""",
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:
- <code>%s</code>
- <code>%s</code>
- <code>%d</code> cores
java runtime:
- <code>%s</code>
- <code>%s</code>
vm memory:
- <code>%d</code> / <code>%d</code> MB
morny version:
- <code>%s</code>
- <code>%s</code>
- <code>%s [UTC]</code>
- [<code>%d</code>]
continuous:
- <code>%s</code>
- [<code>%d</code>]
- <code>%s [UTC]</code>
- [<code>%d</code>]""",
// 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的)今天的运气指数是———— <code>%.2f%%</code> %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());
}
}
}

View File

@ -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.Update;
import com.pengrad.telegrambot.model.request.ParseMode; 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.string.StringArrays;
import cc.sukazyo.untitled.util.telegram.object.InputCommand; 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; 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 { try {

View File

@ -0,0 +1,4 @@
package cc.sukazyo.cono.morny.bot.command;
public class Roll {
}

View File

@ -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(),
"<tg-spoiler>(贴贴喵呜&amp;.&amp;)</tg-spoiler>"
).parseMode(ParseMode.HTML));
}
}
}

View File

@ -4,11 +4,11 @@ import cc.sukazyo.cono.morny.bot.api.EventListenerManager;
public class EventListeners { 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 OnActivityRecord ACTIVITY_RECORDER = new OnActivityRecord();
public static final OnUserSlashAction USER_SLASH_ACTION = new OnUserSlashAction(); public static final OnUserSlashAction USER_SLASH_ACTION = new OnUserSlashAction();
public static final OnUpdateTimestampOffsetLock UPDATE_TIMESTAMP_OFFSET_LOCK = new OnUpdateTimestampOffsetLock(); 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 OnCallMe CALL_ME = new OnCallMe();
public static final OnEventHackHandle EVENT_HACK_HANDLE = new OnEventHackHandle(); public static final OnEventHackHandle EVENT_HACK_HANDLE = new OnEventHackHandle();

View File

@ -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:
- <code>%s</code>
core md5_hash:
- <code>%s</code>
compile timestamp:
- <code>%d</code>
- <code>%s [UTC]</code>""",
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:
- <code>%s</code>
- <code>%s</code>
- <code>%d</code> cores
java runtime:
- <code>%s</code>
- <code>%s</code>
vm memory:
- <code>%d</code> / <code>%d</code> MB
morny version:
- <code>%s</code>
- <code>%s</code>
- <code>%s [UTC]</code>
- [<code>%d</code>]
continuous:
- <code>%s</code>
- [<code>%d</code>]
- <code>%s [UTC]</code>
- [<code>%d</code>]""",
// 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的)今天的运气指数是———— <code>%.2f%%</code> %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());
}
}
}

View File

@ -2,14 +2,12 @@ package cc.sukazyo.cono.morny.bot.event;
import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.MornyCoeur;
import cc.sukazyo.cono.morny.bot.api.EventListener; 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.Update;
import com.pengrad.telegrambot.model.request.InlineQueryResultArticle; import com.pengrad.telegrambot.model.request.InlineQueryResult;
import com.pengrad.telegrambot.model.request.InputTextMessageContent;
import com.pengrad.telegrambot.model.request.ParseMode;
import com.pengrad.telegrambot.request.AnswerInlineQuery; import com.pengrad.telegrambot.request.AnswerInlineQuery;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List;
/** /**
* telegram inlineQuery 功能的处理类 * telegram inlineQuery 功能的处理类
@ -17,21 +15,21 @@ import javax.annotation.Nonnull;
* *
* @since 0.4.1.3 * @since 0.4.1.3
*/ */
public class OnInlineQuery extends EventListener { public class OnInlineQueries extends EventListener {
/** /**
* @since 0.4.1.3 * @since 0.4.1.3
*/ */
@Override @Override
public boolean onInlineQuery (@Nonnull Update update) { public boolean onInlineQuery (@Nonnull Update update) {
MornyCoeur.extra().exec(new AnswerInlineQuery(update.inlineQuery().id(), new InlineQueryResultArticle[]{
new InlineQueryResultArticle( List<InlineQueryResult<?>> results = MornyCoeur.queryManager().query(update);
EncryptUtils.encryptByMD5(update.inlineQuery().query()),
"Raw Input", if (results.size() == 0) return false;
new InputTextMessageContent(update.inlineQuery().query()).parseMode(ParseMode.MarkdownV2)
) MornyCoeur.extra().exec(new AnswerInlineQuery(update.inlineQuery().id(), results.toArray(InlineQueryResult[]::new)));
}));
return true; return true;
} }
} }

View File

@ -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); // 转交命令管理器执行命令
}
}

View File

@ -1,4 +0,0 @@
package cc.sukazyo.cono.morny.bot.event.on_commands;
public class Roll {
}

View File

@ -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 <T extends InlineQueryResult<T>> {
@Nullable
T query (Update event);
}

View File

@ -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<ITelegramQuery<?>> queryInstances = new ArrayList<>();
public MornyQueries () {
queryInstances.add(new RawText());
queryInstances.add(new MyInformation());
}
@Nonnull
public List<InlineQueryResult<?>> query (@Nonnull Update event) {
final List<InlineQueryResult<?>> results = new ArrayList<>();
for (ITelegramQuery<?> instance : queryInstances) {
final InlineQueryResult<?> r = instance.query(event);
if (r!=null) results.add(r);
}
return results;
}
}

View File

@ -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<InlineQueryResultArticle> {
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));
}
}

View File

@ -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<InlineQueryResultArticle> {
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())
);
}
}

View File

@ -62,6 +62,20 @@ public class IP186QueryHandler {
return commonQuery(requestUrl, QUERY_WHOIS_PARAM); return commonQuery(requestUrl, QUERY_WHOIS_PARAM);
} }
/**
* {@link #queryWhois(String)} 的结果进行裁剪.
* <br>
* 将会删除返回内容中 {@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 @Nonnull
private static IP186QueryResponse commonQuery (String requestUrl, String queryIpParam) throws IOException { private static IP186QueryResponse commonQuery (String requestUrl, String queryIpParam) throws IOException {
Request request = new Request.Builder().url(requestUrl + "?" + queryIpParam).build(); Request request = new Request.Builder().url(requestUrl + "?" + queryIpParam).build();

View File

@ -43,7 +43,7 @@ public class TrackerDataManager {
logger.info("CALLED TO EXIT! writing cache."); logger.info("CALLED TO EXIT! writing cache.");
} }
if (record.size() != 0) { if (record.size() != 0) {
save(reset()); save();
} }
else logger.info("nothing to do yet"); else logger.info("nothing to do yet");
} while (!postProcess); } while (!postProcess);

View File

@ -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 :
- <code>%d</code>""",
user.id()
));
if (user.username() == null) {
userInformation.append("\nusername : <u>null</u>");
} else {
userInformation.append(String.format(
"""
username :
- <code>%s</code>""",
escapeHtml(user.username())
));
}
if (user.firstName() == null) {
userInformation.append("\nfirstname : <u>null</u>");
} else {
userInformation.append(String.format(
"""
firstname :
- <code>%s</code>""",
escapeHtml(user.firstName())
));
}
if (user.lastName() == null) {
userInformation.append("\nlastname : <u>null</u>");
} else {
userInformation.append(String.format(
"""
lastname :
- <code>%s</code>""",
escapeHtml(user.lastName())
));
}
if (user.languageCode() != null) {
userInformation.append(String.format(
"""
language-code :
- <code>%s</code>""",
escapeHtml(user.languageCode())
));
}
return userInformation.toString();
}
}