mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-22 11:14:55 +08:00
为error和exit/save 403 实现了 Morny Report,trustedChat= -1,typo 以及文案 fix
- 优化了 coeur 中 exception 的 stackTrace 的输出方式 - 大幅度修改了 EventListenerManager 中报错的逻辑使其更加正常了许多 - 添加了 reportToChat 以及 --report-to 选项用在 MornyReport 中 - 为 coeur 中的错误报告添加了 MornyReport.exception - 为 save/exit 两个需要权限的命令添加了 MornyReport.unauthenticatedAction - 添加了一个方法可以检查 coeur(telegram_bot) 是否已完成初始化以存取 coeur 的内容
This commit is contained in:
parent
618d777463
commit
01b4eea917
@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur
|
||||
MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
|
||||
MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
|
||||
|
||||
VERSION = 1.0.0-alpha4.2
|
||||
VERSION = 1.0.0-alpha5
|
||||
|
||||
USE_DELTA = false
|
||||
VERSION_DELTA =
|
||||
|
@ -3,6 +3,9 @@ package cc.sukazyo.cono.morny;
|
||||
import cc.sukazyo.messiva.Logger;
|
||||
import cc.sukazyo.messiva.appender.ConsoleAppender;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* Morny 的 log 管理器
|
||||
*/
|
||||
@ -15,4 +18,10 @@ public class Log {
|
||||
*/
|
||||
public static final Logger logger = new Logger(new ConsoleAppender());
|
||||
|
||||
public static String exceptionLog (Exception e) {
|
||||
final StringWriter stackTrace = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(stackTrace));
|
||||
return stackTrace.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ public class MornyCoeur {
|
||||
logger.info("Succeed login to @" + remote.username());
|
||||
return new LogInResult(account, remote.username(), remote.id());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(System.out);
|
||||
logger.error(Log.exceptionLog(e));
|
||||
logger.error("login failed.");
|
||||
}
|
||||
}
|
||||
@ -239,6 +239,14 @@ public class MornyCoeur {
|
||||
logger.info("done all save action.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 Coeur 是否已经完成初始化.
|
||||
* @since 1.0.0-alpha5
|
||||
*/
|
||||
public static boolean available() {
|
||||
return INSTANCE != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录成功后的 telegram bot 对象
|
||||
*
|
||||
|
@ -88,6 +88,16 @@ public class MornyConfig {
|
||||
public final boolean commandLoginRefresh;
|
||||
public final boolean commandLogoutClear;
|
||||
|
||||
/* ======================================= *
|
||||
* system: morny report *
|
||||
* ======================================= */
|
||||
|
||||
/**
|
||||
* 控制 Morny Coeur 系统的报告的报告对象.
|
||||
* @since 1.0.0-alpha5
|
||||
*/
|
||||
public final long reportToChat;
|
||||
|
||||
/* ======================================= *
|
||||
* function: dinner query tool *
|
||||
* ======================================= */
|
||||
@ -95,6 +105,10 @@ public class MornyConfig {
|
||||
@Nonnull public final Set<Long> dinnerTrustedReaders;
|
||||
public final long dinnerChatId;
|
||||
|
||||
/* ======================================= *
|
||||
* End Configs | ConfigBuilder *
|
||||
* ======================================= */
|
||||
|
||||
public MornyConfig (@Nonnull Prototype prototype) throws CheckFailure {
|
||||
this.telegramBotApiServer = prototype.telegramBotApiServer;
|
||||
this.telegramBotApiServer4File = prototype.telegramBotApiServer4File;
|
||||
@ -110,6 +124,7 @@ public class MornyConfig {
|
||||
this.commandLogoutClear = prototype.commandLogoutClear;
|
||||
this.dinnerTrustedReaders = prototype.dinnerTrustedReaders;
|
||||
this.dinnerChatId = prototype.dinnerChatId;
|
||||
this.reportToChat = prototype.reportToChat;
|
||||
}
|
||||
|
||||
public static class CheckFailure extends Exception {
|
||||
@ -131,6 +146,7 @@ public class MornyConfig {
|
||||
public boolean commandLogoutClear = false;
|
||||
@Nonnull public Set<Long> dinnerTrustedReaders = new HashSet<>();
|
||||
public long dinnerChatId = -1001707106392L;
|
||||
public long reportToChat = -1001650050443L;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cc.sukazyo.cono.morny;
|
||||
|
||||
import cc.sukazyo.cono.morny.daemon.MornyReport;
|
||||
import cc.sukazyo.cono.morny.util.BuildConfigField;
|
||||
import cc.sukazyo.cono.morny.util.FileUtils;
|
||||
|
||||
@ -135,7 +136,8 @@ public class MornySystem {
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
return "<non-jar-runtime>";
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace(System.out);
|
||||
Log.logger.error(Log.exceptionLog(e));
|
||||
MornyReport.exception(e, "<coeur-md5/calculation-error>");
|
||||
return "<calculation-error>";
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ public class MornyTrusted {
|
||||
*/
|
||||
public boolean isTrusted (long userId) {
|
||||
if (userId == instance.config.trustedMaster) return true;
|
||||
if (instance.config.trustedChat == -1) return false;
|
||||
return MornyCoeur.extra().isUserInGroup(userId, instance.config.trustedChat, Status.administrator);
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,9 @@ public class ServerMain {
|
||||
* {@code --api-files} 单独设定 {@link MornyCoeur#getAccount() bot client} 使用的 telegram bot file api server
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code --report-to} 设定 {@link cc.sukazyo.cono.morny.daemon.MornyReport} 的运行报告要发送到的 telegram 频道
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code --no-hello} 不在主程序启动时输出用于欢迎消息的字符画。
|
||||
* 与 {@code --only-hello} 参数不兼容 —— 会导致程序完全没有任何输出
|
||||
* </li>
|
||||
@ -158,6 +161,10 @@ public class ServerMain {
|
||||
config.telegramBotApiServer4File = args[i];
|
||||
continue;
|
||||
}
|
||||
case "--report-to" -> {
|
||||
config.reportToChat = Long.parseLong(args[i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cc.sukazyo.cono.morny.bot.api;
|
||||
|
||||
import cc.sukazyo.cono.morny.Log;
|
||||
import cc.sukazyo.cono.morny.daemon.MornyReport;
|
||||
import cc.sukazyo.cono.morny.util.tgapi.event.EventRuntimeException;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
@ -32,27 +34,20 @@ public class EventListenerManager {
|
||||
|
||||
if (exec.apply(x)) return;
|
||||
|
||||
} catch (EventRuntimeException e) {
|
||||
|
||||
final StringBuilder errorMessage = new StringBuilder();
|
||||
errorMessage.append("Event runtime breaks: " + e.getMessage()).append('\n');
|
||||
errorMessage.append("at " + e.getStackTrace()[0].toString()).append('\n');
|
||||
errorMessage.append("at " + e.getStackTrace()[1].toString()).append('\n');
|
||||
errorMessage.append("at " + e.getStackTrace()[2].toString()).append('\n');
|
||||
errorMessage.append("at " + e.getStackTrace()[3].toString()).append('\n');
|
||||
if (e instanceof EventRuntimeException.ActionFailed) {
|
||||
errorMessage.append((
|
||||
"\"telegram request track\": " +
|
||||
new GsonBuilder().setPrettyPrinting().create().toJson(((EventRuntimeException.ActionFailed)e).getResponse())
|
||||
).indent(4)).append('\n');
|
||||
}
|
||||
|
||||
logger.error(errorMessage.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
logger.error("Event Error!");
|
||||
e.printStackTrace(System.out);
|
||||
final StringBuilder errorMessage = new StringBuilder();
|
||||
errorMessage.append("Event throws unexpected exception:\n");
|
||||
errorMessage.append(Log.exceptionLog(e).indent(4));
|
||||
if (e instanceof EventRuntimeException.ActionFailed) {
|
||||
errorMessage.append("\ntg-api action: response track: ");
|
||||
errorMessage.append(new GsonBuilder().setPrettyPrinting().create().toJson(
|
||||
((EventRuntimeException.ActionFailed)e).getResponse()
|
||||
).indent(4)).append('\n');
|
||||
}
|
||||
logger.error(errorMessage.toString());
|
||||
|
||||
MornyReport.exception(e, "on event running");
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cc.sukazyo.cono.morny.bot.command;
|
||||
|
||||
import cc.sukazyo.cono.morny.MornyCoeur;
|
||||
import cc.sukazyo.cono.morny.daemon.MornyReport;
|
||||
import cc.sukazyo.cono.morny.data.TelegramStickers;
|
||||
import cc.sukazyo.cono.morny.util.CommonConvert;
|
||||
import cc.sukazyo.cono.morny.util.CommonEncrypt;
|
||||
@ -88,6 +89,7 @@ public class Encryptor implements ITelegramCommand {
|
||||
)).file());
|
||||
} catch (IOException e) {
|
||||
logger.warn("NetworkRequest error: TelegramFileAPI:\n\t" + e.getMessage());
|
||||
MornyReport.exception(e, "NetworkRequest error: TelegramFileAPI");
|
||||
MornyCoeur.extra().exec(new SendSticker(
|
||||
event.message().chat().id(),
|
||||
TelegramStickers.ID_NETWORK_ERR
|
||||
@ -110,6 +112,7 @@ public class Encryptor implements ITelegramCommand {
|
||||
)).file());
|
||||
} catch (IOException e) {
|
||||
logger.warn("NetworkRequest error: TelegramFileAPI:\n\t" + e.getMessage());
|
||||
MornyReport.exception(e, "NetworkRequest error: TelegramFileAPI");
|
||||
MornyCoeur.extra().exec(new SendSticker(
|
||||
event.message().chat().id(),
|
||||
TelegramStickers.ID_NETWORK_ERR
|
||||
|
@ -3,6 +3,7 @@ package cc.sukazyo.cono.morny.bot.command;
|
||||
import cc.sukazyo.cono.morny.BuildConfig;
|
||||
import cc.sukazyo.cono.morny.MornyCoeur;
|
||||
import cc.sukazyo.cono.morny.MornySystem;
|
||||
import cc.sukazyo.cono.morny.daemon.MornyReport;
|
||||
import cc.sukazyo.cono.morny.data.MornyJrrp;
|
||||
import cc.sukazyo.cono.morny.data.TelegramStickers;
|
||||
import cc.sukazyo.cono.morny.util.tgapi.InputCommand;
|
||||
@ -220,6 +221,7 @@ public class MornyCommands {
|
||||
).replyToMessageId(event.message().messageId())
|
||||
);
|
||||
logger.info("403 exited tag from user " + TGToString.as(event.message().from()).toStringLogTag());
|
||||
MornyReport.unauthenticatedAction("/exit", event.message().from());
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,6 +377,7 @@ public class MornyCommands {
|
||||
).replyToMessageId(event.message().messageId())
|
||||
);
|
||||
logger.info("403 call save tag from user " + TGToString.as(event.message().from()).toStringLogTag());
|
||||
MornyReport.unauthenticatedAction("/save", event.message().from());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ public class Testing implements ISimpleCommand {
|
||||
|
||||
MornyCoeur.extra().exec(new SendMessage(
|
||||
event.message().chat().id(),
|
||||
"<b>Just<b/> a TEST command."
|
||||
"<b>Just</b> a TEST command."
|
||||
).replyToMessageId(event.message().messageId()).parseMode(ParseMode.HTML));
|
||||
|
||||
}
|
||||
|
@ -22,12 +22,13 @@ public class 私わね implements ISimpleCommand {
|
||||
public void execute (@Nonnull InputCommand command, @Nonnull Update event) {
|
||||
if (ThreadLocalRandom.current().nextInt(521) == 0) {
|
||||
// 可以接入未来的心情系统(如果有的话)
|
||||
final String text = switch (ThreadLocalRandom.current().nextInt(11)) {
|
||||
case 0,7,8,9,10 -> "才不是";
|
||||
case 1,2,3,6 -> "才不是!";
|
||||
case 4,5 -> "才不是..";
|
||||
default -> throw new IllegalStateException("Unexpected random value in 私わね command.");
|
||||
};
|
||||
// final String text = switch (ThreadLocalRandom.current().nextInt(11)) {
|
||||
// case 0,7,8,9,10 -> "才不是";
|
||||
// case 1,2,3,6 -> "才不是!";
|
||||
// case 4,5 -> "才不是..";
|
||||
// default -> throw new IllegalStateException("Unexpected random value in 私わね command.");
|
||||
// };
|
||||
final String text = "/打假";
|
||||
MornyCoeur.extra().exec(new SendMessage(
|
||||
event.message().chat().id(),
|
||||
text
|
||||
|
@ -12,6 +12,7 @@ import com.pengrad.telegrambot.response.SendResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cc.sukazyo.cono.morny.Log.exceptionLog;
|
||||
import static cc.sukazyo.cono.morny.Log.logger;
|
||||
|
||||
public class MedicationTimer extends Thread {
|
||||
@ -40,7 +41,8 @@ public class MedicationTimer extends Thread {
|
||||
logger.info("MedicationTimer was interrupted, will be exit now");
|
||||
} catch (Exception e) {
|
||||
logger.error("Unexpected error occurred");
|
||||
e.printStackTrace(System.out);
|
||||
logger.error(exceptionLog(e));
|
||||
MornyReport.exception(e);
|
||||
}
|
||||
}
|
||||
logger.info("MedicationTimer stopped");
|
||||
|
67
src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java
Normal file
67
src/main/java/cc/sukazyo/cono/morny/daemon/MornyReport.java
Normal file
@ -0,0 +1,67 @@
|
||||
package cc.sukazyo.cono.morny.daemon;
|
||||
|
||||
import cc.sukazyo.cono.morny.Log;
|
||||
import cc.sukazyo.cono.morny.MornyCoeur;
|
||||
import cc.sukazyo.cono.morny.util.tgapi.event.EventRuntimeException;
|
||||
import cc.sukazyo.cono.morny.util.tgapi.formatting.TGToString;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.pengrad.telegrambot.model.User;
|
||||
import com.pengrad.telegrambot.model.request.ParseMode;
|
||||
import com.pengrad.telegrambot.request.BaseRequest;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import com.pengrad.telegrambot.response.BaseResponse;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static cc.sukazyo.cono.morny.util.tgapi.formatting.MsgEscape.escapeHtml;
|
||||
|
||||
public class MornyReport {
|
||||
|
||||
private static <T extends BaseRequest<T, R>, R extends BaseResponse> void executeReport (@Nonnull T report) {
|
||||
if (!MornyCoeur.available()) return;
|
||||
try {
|
||||
MornyCoeur.extra().exec(report);
|
||||
} catch (EventRuntimeException.ActionFailed e) {
|
||||
Log.logger.warn("cannot execute report to telegram:");
|
||||
Log.logger.warn(Log.exceptionLog(e));
|
||||
}
|
||||
}
|
||||
|
||||
public static void exception (@Nonnull Exception e, @Nullable String description) {
|
||||
if (!MornyCoeur.available()) return;
|
||||
executeReport(new SendMessage(
|
||||
MornyCoeur.config().reportToChat,
|
||||
String.format("""
|
||||
<b>▌Coeur Unexpected Exception</b>
|
||||
%s
|
||||
<pre><code>%s</code></pre>%s
|
||||
""",
|
||||
description == null ? "" : escapeHtml(description)+"\n",
|
||||
escapeHtml(Log.exceptionLog(e)),
|
||||
e instanceof EventRuntimeException.ActionFailed ? (String.format(
|
||||
"\n\ntg-api error:\n<pre><code>%s</code></pre>",
|
||||
new GsonBuilder().setPrettyPrinting().create().toJson(((EventRuntimeException.ActionFailed)e).getResponse()))
|
||||
) : ""
|
||||
)
|
||||
).parseMode(ParseMode.HTML));
|
||||
}
|
||||
|
||||
public static void exception (@Nonnull Exception e) { exception(e, null); }
|
||||
|
||||
public static void unauthenticatedAction (@Nonnull String action, @Nonnull User user) {
|
||||
if (!MornyCoeur.available()) return;
|
||||
executeReport(new SendMessage(
|
||||
MornyCoeur.config().reportToChat,
|
||||
String.format("""
|
||||
<b>▌User unauthenticated action</b>
|
||||
action: %s
|
||||
by user %s
|
||||
""",
|
||||
escapeHtml(action),
|
||||
TGToString.as(user).fullnameRefHtml()
|
||||
)
|
||||
).parseMode(ParseMode.HTML));
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@ import java.util.HashMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static cc.sukazyo.cono.morny.Log.exceptionLog;
|
||||
import static cc.sukazyo.cono.morny.Log.logger;
|
||||
|
||||
public class TrackerDataManager {
|
||||
@ -113,8 +114,10 @@ public class TrackerDataManager {
|
||||
));
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error(String.format("exception in write tracker data: %d/%d/%d", chat, user, timestamp));
|
||||
e.printStackTrace(System.out);
|
||||
final String message = String.format("exception in write tracker data: %d/%d/%d", chat, user, timestamp);
|
||||
logger.error(message);
|
||||
logger.error(exceptionLog(e));
|
||||
MornyReport.exception(e, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user