mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-22 19:24:53 +08:00
添加了 morny login/exit 的报告,*msg 现在支持了只包含发送 id 不包含发送体
- 为 MornyCoeur 添加了 whileExitReason (exit/getExitReason) 接口,用于安全退出时指定推出原因 - MornyConfig 添加了一个 Sensitive 注解用于标明字段值属于敏感字段不应该被打印 -
This commit is contained in:
parent
01b4eea917
commit
3689962cb3
@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur
|
|||||||
MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
|
MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
|
||||||
MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
|
MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
|
||||||
|
|
||||||
VERSION = 1.0.0-alpha5
|
VERSION = 1.0.0-alpha6
|
||||||
|
|
||||||
USE_DELTA = false
|
USE_DELTA = false
|
||||||
VERSION_DELTA =
|
VERSION_DELTA =
|
||||||
|
@ -60,6 +60,8 @@ public class MornyCoeur {
|
|||||||
*/
|
*/
|
||||||
public static final long coeurStartTimestamp = ServerMain.systemStartupTime;
|
public static final long coeurStartTimestamp = ServerMain.systemStartupTime;
|
||||||
|
|
||||||
|
private Object whileExitReason = null;
|
||||||
|
|
||||||
private record LogInResult(TelegramBot account, String username, long userid) { }
|
private record LogInResult(TelegramBot account, String username, long userid) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,7 +154,6 @@ public class MornyCoeur {
|
|||||||
* 用于退出时进行缓存的任务处理等进行安全退出
|
* 用于退出时进行缓存的任务处理等进行安全退出
|
||||||
*/
|
*/
|
||||||
private void exitCleanup () {
|
private void exitCleanup () {
|
||||||
logger.info("clean:save tracker data.");
|
|
||||||
MornyDaemons.stop();
|
MornyDaemons.stop();
|
||||||
if (config.commandLogoutClear) {
|
if (config.commandLogoutClear) {
|
||||||
commandManager.automaticRemoveList();
|
commandManager.automaticRemoveList();
|
||||||
@ -304,4 +305,13 @@ public class MornyCoeur {
|
|||||||
|
|
||||||
public static long getUserid () { return INSTANCE.userid; }
|
public static long getUserid () { return INSTANCE.userid; }
|
||||||
|
|
||||||
|
public static void exit (int status, Object reason) {
|
||||||
|
INSTANCE.whileExitReason = reason;
|
||||||
|
System.exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getExitReason () {
|
||||||
|
return INSTANCE.whileExitReason;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,20 @@ package cc.sukazyo.cono.morny;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.lang.annotation.*;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class MornyConfig {
|
public class MornyConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表示一个字段的值属于敏感数据,不应该被执行打印等操作。
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
|
public @interface Sensitive {}
|
||||||
|
|
||||||
/* ======================================= *
|
/* ======================================= *
|
||||||
* Config props Names Definition *
|
* Config props Names Definition *
|
||||||
* ======================================= */
|
* ======================================= */
|
||||||
@ -37,7 +46,7 @@ public class MornyConfig {
|
|||||||
* <p>
|
* <p>
|
||||||
* 这个值必须设定。
|
* 这个值必须设定。
|
||||||
*/
|
*/
|
||||||
@Nonnull public final String telegramBotKey;
|
@Nonnull @Sensitive public final String telegramBotKey;
|
||||||
/**
|
/**
|
||||||
* morny 所使用的 bot 的 username.
|
* morny 所使用的 bot 的 username.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -213,7 +213,7 @@ public class MornyCommands {
|
|||||||
).replyToMessageId(event.message().messageId())
|
).replyToMessageId(event.message().messageId())
|
||||||
);
|
);
|
||||||
logger.info("Morny exited by user " + TGToString.as(event.message().from()).toStringLogTag());
|
logger.info("Morny exited by user " + TGToString.as(event.message().from()).toStringLogTag());
|
||||||
System.exit(0);
|
MornyCoeur.exit(0, event.message().from());
|
||||||
} else {
|
} else {
|
||||||
MornyCoeur.extra().exec(new SendSticker(
|
MornyCoeur.extra().exec(new SendSticker(
|
||||||
event.message().chat().id(),
|
event.message().chat().id(),
|
||||||
|
@ -27,12 +27,12 @@ import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml;
|
|||||||
|
|
||||||
public class OnCallMsgSend extends EventListener {
|
public class OnCallMsgSend extends EventListener {
|
||||||
|
|
||||||
private static final Pattern REGEX_MSG_SENDREQ_DATA_HEAD = Pattern.compile("^\\*msg([\\d-]+)(\\*\\S+)?\\n([\\s\\S]+)$");
|
private static final Pattern REGEX_MSG_SENDREQ_DATA_HEAD = Pattern.compile("^\\*msg(-?\\d+)(\\*\\S+)?(?:\\n([\\s\\S]+))?$");
|
||||||
|
|
||||||
private record MessageToSend (
|
private record MessageToSend (
|
||||||
String message,
|
@Nullable String message,
|
||||||
MessageEntity[] entities,
|
@Nullable MessageEntity[] entities,
|
||||||
ParseMode parseMode,
|
@Nullable ParseMode parseMode,
|
||||||
long targetId
|
long targetId
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ public class OnCallMsgSend extends EventListener {
|
|||||||
// 发送体处理
|
// 发送体处理
|
||||||
if (update.message().replyToMessage() == null) return answer404(update);
|
if (update.message().replyToMessage() == null) return answer404(update);
|
||||||
msgsendReqBody = parseRequest(update.message().replyToMessage());
|
msgsendReqBody = parseRequest(update.message().replyToMessage());
|
||||||
if (msgsendReqBody == null) return answer404(update);
|
if (msgsendReqBody == null || msgsendReqBody.message == null) return answer404(update);
|
||||||
// 执行发送任务
|
// 执行发送任务
|
||||||
SendResponse sendResponse = MornyCoeur.getAccount().execute(parseMessageToSend(msgsendReqBody));
|
SendResponse sendResponse = MornyCoeur.getAccount().execute(parseMessageToSend(msgsendReqBody));
|
||||||
if (!sendResponse.isOk()) { // 发送失败
|
if (!sendResponse.isOk()) { // 发送失败
|
||||||
@ -150,7 +150,8 @@ public class OnCallMsgSend extends EventListener {
|
|||||||
).replyToMessageId(update.message().messageId()).parseMode(ParseMode.HTML));
|
).replyToMessageId(update.message().messageId()).parseMode(ParseMode.HTML));
|
||||||
}
|
}
|
||||||
// 发送文本测试
|
// 发送文本测试
|
||||||
SendResponse testSendResp = MornyCoeur.getAccount().execute(
|
if (msgsendReqBody.message == null) return true;
|
||||||
|
final SendResponse testSendResp = MornyCoeur.getAccount().execute(
|
||||||
parseMessageToSend(msgsendReqBody, update.message().chat().id()).replyToMessageId(update.message().messageId())
|
parseMessageToSend(msgsendReqBody, update.message().chat().id()).replyToMessageId(update.message().messageId())
|
||||||
);
|
);
|
||||||
if (!testSendResp.isOk()) {
|
if (!testSendResp.isOk()) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cc.sukazyo.cono.morny.daemon;
|
package cc.sukazyo.cono.morny.daemon;
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.MornyCoeur;
|
||||||
|
|
||||||
import static cc.sukazyo.cono.morny.Log.logger;
|
import static cc.sukazyo.cono.morny.Log.logger;
|
||||||
|
|
||||||
public class MornyDaemons {
|
public class MornyDaemons {
|
||||||
@ -10,6 +12,7 @@ public class MornyDaemons {
|
|||||||
logger.info("ALL Morny Daemons starting...");
|
logger.info("ALL Morny Daemons starting...");
|
||||||
// TrackerDataManager.init();
|
// TrackerDataManager.init();
|
||||||
medicationTimerInstance.start();
|
medicationTimerInstance.start();
|
||||||
|
MornyReport.onMornyLogIn();
|
||||||
logger.info("Morny Daemons started.");
|
logger.info("Morny Daemons started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ public class MornyDaemons {
|
|||||||
// TrackerDataManager.trackingLock.lock();
|
// TrackerDataManager.trackingLock.lock();
|
||||||
try { medicationTimerInstance.join(); } catch (InterruptedException e) { e.printStackTrace(System.out); }
|
try { medicationTimerInstance.join(); } catch (InterruptedException e) { e.printStackTrace(System.out); }
|
||||||
|
|
||||||
|
MornyReport.onMornyExit(MornyCoeur.getExitReason());
|
||||||
logger.info("ALL Morny Daemons STOPPED.");
|
logger.info("ALL Morny Daemons STOPPED.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package cc.sukazyo.cono.morny.daemon;
|
|||||||
|
|
||||||
import cc.sukazyo.cono.morny.Log;
|
import cc.sukazyo.cono.morny.Log;
|
||||||
import cc.sukazyo.cono.morny.MornyCoeur;
|
import cc.sukazyo.cono.morny.MornyCoeur;
|
||||||
|
import cc.sukazyo.cono.morny.MornyConfig;
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.event.EventRuntimeException;
|
import cc.sukazyo.cono.morny.util.tgapi.event.EventRuntimeException;
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString;
|
import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
@ -14,6 +15,9 @@ import com.pengrad.telegrambot.response.BaseResponse;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import static cc.sukazyo.cono.morny.Log.logger;
|
||||||
import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml;
|
import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml;
|
||||||
|
|
||||||
public class MornyReport {
|
public class MornyReport {
|
||||||
@ -23,8 +27,10 @@ public class MornyReport {
|
|||||||
try {
|
try {
|
||||||
MornyCoeur.extra().exec(report);
|
MornyCoeur.extra().exec(report);
|
||||||
} catch (EventRuntimeException.ActionFailed e) {
|
} catch (EventRuntimeException.ActionFailed e) {
|
||||||
Log.logger.warn("cannot execute report to telegram:");
|
logger.warn("cannot execute report to telegram:");
|
||||||
Log.logger.warn(Log.exceptionLog(e));
|
logger.warn(Log.exceptionLog(e).indent(4));
|
||||||
|
logger.warn("tg-api response:");
|
||||||
|
logger.warn(e.getResponse().toString().indent(4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,4 +70,85 @@ public class MornyReport {
|
|||||||
).parseMode(ParseMode.HTML));
|
).parseMode(ParseMode.HTML));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* morny 登陆时的报告发送,包含已登录的账号 id 以及启动配置。
|
||||||
|
* @since 1.0.0-alpha6
|
||||||
|
*/
|
||||||
|
public static void onMornyLogIn () {
|
||||||
|
executeReport(new SendMessage(
|
||||||
|
MornyCoeur.config().reportToChat,
|
||||||
|
String.format("""
|
||||||
|
<b>▌Morny Logged in</b>
|
||||||
|
as user @%s
|
||||||
|
|
||||||
|
as config fields:
|
||||||
|
%s
|
||||||
|
""",
|
||||||
|
MornyCoeur.getUsername(),
|
||||||
|
sectionConfigFields(MornyCoeur.config())
|
||||||
|
)
|
||||||
|
).parseMode(ParseMode.HTML));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回一个 config 字段与值的列表,可以作为 telegram html 格式输出
|
||||||
|
* @since 1.0.0-alpha6
|
||||||
|
*/
|
||||||
|
private static String sectionConfigFields (@Nonnull MornyConfig config) {
|
||||||
|
final StringBuilder echo = new StringBuilder();
|
||||||
|
for (Field field : config.getClass().getFields()) {
|
||||||
|
echo.append("- <i><u>").append(field.getName()).append("</u></i> ");
|
||||||
|
try {
|
||||||
|
if (field.isAnnotationPresent(MornyConfig.Sensitive.class)) {
|
||||||
|
echo.append(": <i>sensitive_field</i>");
|
||||||
|
} else {
|
||||||
|
final Object fieldValue = field.get(config);
|
||||||
|
echo.append("= ");
|
||||||
|
if (fieldValue == null)
|
||||||
|
echo.append("null");
|
||||||
|
else echo.append("<code>").append(escapeHtml(fieldValue.toString())).append("</code>");
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException | IllegalArgumentException | NullPointerException e) {
|
||||||
|
echo.append(": <i>").append(escapeHtml("<read-error>")).append("</i>");
|
||||||
|
logger.error("error while reading config field " + field.getName());
|
||||||
|
logger.error(Log.exceptionLog(e));
|
||||||
|
exception(e, "error while reading config field " + field.getName());
|
||||||
|
}
|
||||||
|
echo.append("\n");
|
||||||
|
}
|
||||||
|
return echo.substring(0, echo.length()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* morny 关闭/登出时发送的报告.
|
||||||
|
* <p>
|
||||||
|
* 基于 java 的程序关闭钩子,因此仍然无法在意外宕机的情况下发送报告.
|
||||||
|
* @param causedBy
|
||||||
|
* 关闭的原因。
|
||||||
|
* 可以使用 {@link User Telegram 用户对象} 表示由一个用户执行了关闭,
|
||||||
|
* 传入其它数据将使用 {@code #toString} 输出其内容。
|
||||||
|
* 传入 {@link null} 则表示不表明原因。
|
||||||
|
*/
|
||||||
|
static void onMornyExit (@Nullable Object causedBy) {
|
||||||
|
if (!MornyCoeur.available()) return;
|
||||||
|
String causedTag = null;
|
||||||
|
if (causedBy != null) {
|
||||||
|
if (causedBy instanceof User)
|
||||||
|
causedTag = TGToString.as((User)causedBy).fullnameRefHtml();
|
||||||
|
else
|
||||||
|
causedTag = "<code>" + escapeHtml(causedBy.toString()) + "</code>";
|
||||||
|
}
|
||||||
|
executeReport(new SendMessage(
|
||||||
|
MornyCoeur.config().reportToChat,
|
||||||
|
String.format("""
|
||||||
|
<b>▌Morny Exited</b>
|
||||||
|
from user @%s
|
||||||
|
%s
|
||||||
|
""",
|
||||||
|
MornyCoeur.getUsername(),
|
||||||
|
causedBy == null ? "with UNKNOWN reason" : "\nby " + causedTag
|
||||||
|
)
|
||||||
|
).parseMode(ParseMode.HTML));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user