diff --git a/gradle.properties b/gradle.properties index d9dfb9e..4280de8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ ## Core -VERSION = 0.7.0.7 +VERSION = 0.7.0.8 # dependencies diff --git a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java index f97e70e..9536859 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.7.0.7"; - public static final long COMPILE_TIMESTAMP = 1653044177443L; + public static final String VERSION = "0.7.0.8"; + public static final long COMPILE_TIMESTAMP = 1653132713941L; } 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 2f62796..53d6c72 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 @@ -13,6 +13,7 @@ public class EventListeners { public static final OnEventHackHandle EVENT_HACK_HANDLE = new OnEventHackHandle(); public static final OnKuohuanhuanNeedSleep KUOHUANHUAN_NEED_SLEEP = new OnKuohuanhuanNeedSleep(); public static final OnUserRandoms USER_RANDOMS = new OnUserRandoms(); + public static final OnCallMsgSend CALL_MSG_SEND = new OnCallMsgSend(); public static void registerAllListeners () { EventListenerManager.addListener( @@ -24,6 +25,7 @@ public class EventListeners { USER_SLASH_ACTION, INLINE_QUERY, CALL_ME, + CALL_MSG_SEND, EVENT_HACK_HANDLE ); } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java new file mode 100644 index 0000000..e54a443 --- /dev/null +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMsgSend.java @@ -0,0 +1,215 @@ +package cc.sukazyo.cono.morny.bot.event; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.pengrad.telegrambot.model.Chat; +import com.pengrad.telegrambot.model.Message; +import com.pengrad.telegrambot.model.MessageEntity; +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.ParseMode; +import com.pengrad.telegrambot.request.GetChat; +import com.pengrad.telegrambot.request.SendMessage; +import com.pengrad.telegrambot.request.SendSticker; + +import cc.sukazyo.cono.morny.MornyCoeur; +import cc.sukazyo.cono.morny.bot.api.EventListener; +import cc.sukazyo.cono.morny.data.TelegramStickers; +import com.pengrad.telegrambot.response.GetChatResponse; +import com.pengrad.telegrambot.response.SendResponse; + +import static cc.sukazyo.untitled.util.telegram.formatting.MsgEscape.escapeHtml; + +public class OnCallMsgSend extends EventListener { + + private static final Pattern REGEX_MSG_SENDREQ_DATA_HEAD = Pattern.compile("^\\*msg([\\d-]+)(\\*\\S+)?\\n([\\s\\S]+)$"); + + private record MessageToSend ( + String message, + MessageEntity[] entities, + ParseMode parseMode, + long targetId + ) { } + + @Override + public boolean onMessage(Update update) { + + // 执行体检查 + if (update.message().chat().type() != Chat.Type.Private) return false; + if (update.message().text() == null) return false; + if (!update.message().text().startsWith("*msg")) return false; + + // 权限检查 + if (!MornyCoeur.trustedInstance().isTrusted(update.message().from().id())) { + MornyCoeur.extra().exec(new SendSticker( + update.message().chat().id(), + TelegramStickers.ID_403 + ).replyToMessageId(update.message().messageId())); + return true; + } + + Message msgsendReqRaw; // 用户书写的发送请求原文 + MessageToSend msgsendReqBody; // 解析后的发送请求实例 + + // *msgsend 发送标识 + // 处理发送要求 + if (update.message().text().equals("*msgsend")) { + // 发送体处理 + if (update.message().replyToMessage() == null) return answer404(update); + msgsendReqBody = parseRequest(update.message().replyToMessage()); + if (msgsendReqBody == null) return answer404(update); + // 执行发送任务 + SendResponse sendResponse = MornyCoeur.getAccount().execute(parseMessageToSend(msgsendReqBody)); + if (!sendResponse.isOk()) { // 发送失败 + MornyCoeur.extra().exec(new SendMessage( + update.message().chat().id(), + String.format(""" + %d FAILED + %s""", + sendResponse.errorCode(), + sendResponse.description() + ) + ).replyToMessageId(update.message().messageId()).parseMode(ParseMode.HTML)); + } + return true; + // 发送完成/失败 - 事件结束 + } + + // *msg 检查标识 + if (update.message().text().equals("*msg")) { // 处理对曾经的原文的检查 + if (update.message().replyToMessage() == null) { + return answer404(update); + } + msgsendReqRaw = update.message().replyToMessage(); + } else if (update.message().text().startsWith("*msg")) { // 对接受到的原文进行检查 + msgsendReqRaw = update.message(); + } else { + return answer404(update); // 未定义的动作 + } + + // 对发送请求的用户原文进行解析 + msgsendReqBody = parseRequest(msgsendReqRaw); + if (msgsendReqBody == null) { + return answer404(update); + } + + // 输出发送目标信息 + GetChatResponse targetChatReq = MornyCoeur.getAccount().execute(new GetChat(msgsendReqBody.targetId())); + if (!targetChatReq.isOk()) { + MornyCoeur.extra().exec(new SendMessage( + update.message().chat().id(), + String.format(""" + %d FAILED + %s""", + targetChatReq.errorCode(), + targetChatReq.description() + ) + ).replyToMessageId(update.message().messageId()).parseMode(ParseMode.HTML)); + } { + MornyCoeur.extra().exec(new SendMessage( + update.message().chat().id(), + targetChatReq.chat().type()== Chat.Type.Private ? ( + String.format(""" + %d@%s + 🔒 %s %s""", + msgsendReqBody.targetId(), + escapeHtml(targetChatReq.chat().type().name()), + escapeHtml(targetChatReq.chat().firstName()+(targetChatReq.chat().lastName()==null?"":" "+targetChatReq.chat().lastName())), + targetChatReq.chat().username()==null? + String.format("@@", targetChatReq.chat().id()): + (escapeHtml("@"+targetChatReq.chat().username())) + ) + ) : ( + String.format(""" + %d@%s::: + %s %s%s""", + msgsendReqBody.targetId(), + escapeHtml(targetChatReq.chat().type().name()), + switch (targetChatReq.chat().type()) { + case group -> "💭"; + case channel -> "📢"; + case supergroup -> "💬"; + default -> "⭕️"; + }, + escapeHtml(targetChatReq.chat().title()), + targetChatReq.chat().username() != null?String.format( + " @%s", escapeHtml(targetChatReq.chat().username()) + ):"" + ) + ) + ).replyToMessageId(update.message().messageId()).parseMode(ParseMode.HTML)); + } + // 发送文本测试 + SendResponse testSendResp = MornyCoeur.getAccount().execute( + parseMessageToSend(msgsendReqBody, update.message().chat().id()).replyToMessageId(update.message().messageId()) + ); + if (!testSendResp.isOk()) { + MornyCoeur.extra().exec(new SendMessage( + update.message().chat().id(), + String.format(""" + %d FAILED + %s""", + testSendResp.errorCode(), + testSendResp.description() + ) + ).replyToMessageId(update.message().messageId()).parseMode(ParseMode.HTML)); + } + + return true; + + } + + @Nullable + private static MessageToSend parseRequest (@Nonnull Message requestBody) { + + final Matcher matcher = REGEX_MSG_SENDREQ_DATA_HEAD.matcher(requestBody.text()); + if (matcher.matches()) { + long targetId = Long.parseLong(matcher.group(1)); + ParseMode parseMode = matcher.group(2) == null ? null : switch (matcher.group(2)) { + case "*markdown", "*md", "*m↓" -> ParseMode.MarkdownV2; + case "*md1" -> ParseMode.Markdown; + case "*html" -> ParseMode.HTML; + default -> null; + }; + final int offset = "*msg".length()+matcher.group(1).length()+(matcher.group(2)==null?0:matcher.group(2).length())+1; + final ArrayList entities = new ArrayList<>(); + if (requestBody.entities() != null) for (MessageEntity entity : requestBody.entities()) { + final MessageEntity parsed = new MessageEntity(entity.type(), entity.offset() - offset, entity.length()); + if (entity.url() != null) parsed.url(entity.url()); + if (entity.user() != null) parsed.user(entity.user()); + if (entity.language() != null) parsed.language(entity.language()); + entities.add(parsed); + } + return new MessageToSend(matcher.group(3), entities.toArray(MessageEntity[]::new), parseMode, targetId); + } + + return null; + + } + + @Nonnull + private static SendMessage parseMessageToSend (@Nonnull MessageToSend body) { + return parseMessageToSend(body, body.targetId); + } + + @Nonnull + private static SendMessage parseMessageToSend (@Nonnull MessageToSend body, long targetId) { + SendMessage sendingBody = new SendMessage(targetId, body.message); + if (body.entities != null) sendingBody.entities(body.entities); + if (body.parseMode != null) sendingBody.parseMode(body.parseMode); + return sendingBody; + } + + private static boolean answer404 (@Nonnull Update update) { + MornyCoeur.extra().exec(new SendSticker( + update.message().chat().id(), + TelegramStickers.ID_404 + ).replyToMessageId(update.message().messageId())); + return true; + } + +}