diff --git a/gradle.properties b/gradle.properties
index 38fb156..a3de3a3 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,6 @@
## Core
-VERSION = 0.4.2.6
+VERSION = 0.4.2.7
# dependencies
diff --git a/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java b/src/main/java/cc/sukazyo/cono/morny/GradleProjectConfigures.java
index 5b30b66..f7af85d 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.2.6";
- public static final long COMPILE_TIMESTAMP = 1640065256004L;
+ public static final String VERSION = "0.4.2.7";
+ public static final long COMPILE_TIMESTAMP = 1640104964102L;
}
diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java b/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java
index c6fdf0d..06d7944 100644
--- a/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java
+++ b/src/main/java/cc/sukazyo/cono/morny/MornyCoeur.java
@@ -17,8 +17,14 @@ import static cc.sukazyo.cono.morny.Log.logger;
*/
public class MornyCoeur {
+ /** 当前程序的 Morny Coeur 实例 */
+ private static MornyCoeur INSTANCE;
+
+ /** 当前 Morny 的{@link MornyTrusted 信任验证机}实例 */
+ private final MornyTrusted trusted;
+
/** morny 的 bot 账户 */
- private static TelegramBot account;
+ private final TelegramBot account;
/**
* morny 的 bot 账户的用户名
*
@@ -28,36 +34,40 @@ public class MornyCoeur {
* 如果在登陆之前就定义了此字段,则登陆代码会验证登陆的 bot 的 username
* 是否与定义的 username 符合。如果不符合则会报错。
*/
- private static String username;
+ private final String username;
/**
* morny 的事件忽略前缀时间
*
* {@link cc.sukazyo.cono.morny.bot.event.OnUpdateTimestampOffsetLock}
* 会根据这里定义的时间戳取消掉比此时间更早的事件链
*/
- public static long latestEventTimestamp;
+ public long latestEventTimestamp;
/**
* morny 主程序启动时间
* 用于统计数据
*/
public static final long coeurStartTimestamp = System.currentTimeMillis();
+ private record LogInResult(TelegramBot account, String username) { }
+
/**
- * bot 启动入口,执行 bot 初始化
+ * 执行 bot 初始化
*
* @param botKey bot 的 telegram bot api token
* @param botUsername bot 的 username 限定。如果为 null 则表示不限定,
* 如果指定,则登录时会检查所登陆的 bot 的用户名是否与此相等
+ * @param master morny 实例所信任的主人的 id。用于初始化 {@link #trusted}
+ * @param trustedChat morny 实例所信任的群组的 id。用于初始化 {@link #trusted}
* @param latestEventTimestamp 事件处理器会处理事件的最早时间戳 ——
* 只有限定的 message 事件会受此影响。
* 单位为毫秒
*/
- public static void main (@Nonnull String botKey, @Nullable String botUsername, long latestEventTimestamp) {
-
- MornyCoeur.latestEventTimestamp = latestEventTimestamp;
-
- logger.info("System Starting");
+ private MornyCoeur (
+ @Nonnull String botKey, @Nullable String botUsername,
+ long master, long trustedChat, long latestEventTimestamp
+ ) {
+ this.latestEventTimestamp = latestEventTimestamp;
configureSafeExit();
logger.info("args key:\n " + botKey);
@@ -65,23 +75,57 @@ public class MornyCoeur {
logger.info("login as:\n " + botUsername);
}
- try { account = login(botKey); }
- catch (Exception e) { logger.error("Cannot login to bot/api. :\n " + e.getMessage()); System.exit(-1); }
+ try {
+ final LogInResult loginResult = login(botKey);
+ this.account = loginResult.account;
+ this.username = loginResult.username;
+ this.trusted = new MornyTrusted(master, trustedChat);
+ logger.info(String.format("""
+ trusted param set:
+ - master (id)
+ %d
+ - trusted chat (id)
+ %d""",
+ master, trustedChat
+ ));
+ }
+ catch (Exception e) {
+ RuntimeException ex = new RuntimeException("Cannot login to bot/api. :\n " + e.getMessage());
+ logger.error(ex.getMessage());
+ throw ex;
+ }
logger.info("Bot login succeed.");
- TrackerDataManager.init();
- EventListeners.registerAllListeners();
- account.setUpdatesListener(OnUpdate::onNormalUpdate);
-
- logger.info("System start complete");
-
+ }
+
+ /**
+ * 向外界暴露的 morny 初始化入口.
+ *
+ * 如果 morny 已经初始化,则不会进行初始化,抛出错误消息并直接退出方法。
+ *
+ * @see #MornyCoeur 程序初始化方法
+ */
+ public static void main (
+ @Nonnull String botKey, @Nullable String botUsername,
+ long master, long trustedChat, long latestEventTimestamp
+ ) {
+ if (INSTANCE == null) {
+ logger.info("System Starting");
+ INSTANCE = new MornyCoeur(botKey, botUsername, master, trustedChat, latestEventTimestamp);
+ TrackerDataManager.init();
+ EventListeners.registerAllListeners();
+ INSTANCE.account.setUpdatesListener(OnUpdate::onNormalUpdate);
+ logger.info("System start complete");
+ return;
+ }
+ logger.error("System already started coeur!!!");
}
/**
* 用于退出时进行缓存的任务处理等进行安全退出
*/
- private static void exitCleanup () {
+ private void exitCleanup () {
TrackerDataManager.DAEMON.interrupt();
TrackerDataManager.trackingLock.lock();
}
@@ -89,8 +133,8 @@ public class MornyCoeur {
/**
* 为程序在虚拟机上添加退出钩子
*/
- private static void configureSafeExit () {
- Runtime.getRuntime().addShutdownHook(new Thread(MornyCoeur::exitCleanup));
+ private void configureSafeExit () {
+ Runtime.getRuntime().addShutdownHook(new Thread(this::exitCleanup));
}
/**
@@ -104,18 +148,17 @@ public class MornyCoeur {
* @return 成功登录后的 {@link TelegramBot} 对象
*/
@Nonnull
- public static TelegramBot login (@Nonnull String key) {
+ private LogInResult login (@Nonnull String key) {
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 (MornyCoeur.username != null && !MornyCoeur.username.equals(username))
- throw new RuntimeException("Required the bot @" + MornyCoeur.username + " but @" + username + " logged in!");
- else MornyCoeur.username = username;
+ if (this.username != null && !this.username.equals(username))
+ throw new RuntimeException("Required the bot @" + this.username + " but @" + username + " logged in!");
logger.info("Succeed login to @" + username);
- return account;
+ return new LogInResult(account, username);
} catch (Exception e) {
e.printStackTrace(System.out);
logger.error("login failed.");
@@ -129,8 +172,9 @@ public class MornyCoeur {
*
* @return {@link #account MornyCoeur.account}
*/
+ @Nonnull
public static TelegramBot getAccount () {
- return account;
+ return INSTANCE.account;
}
/**
@@ -138,8 +182,29 @@ public class MornyCoeur {
*
* @return {@link #username MornyCoeur.username}
*/
+ @Nonnull
public static String getUsername () {
- return username;
+ return INSTANCE.username;
+ }
+
+ /**
+ *
+ * 获取忽略时间点
+ *
+ * @return {@link #latestEventTimestamp MornyCoeur.latestEventTimestamp}
+ */
+ public static long getLatestEventTimestamp () {
+ return INSTANCE.latestEventTimestamp;
+ }
+
+ /**
+ * 获取 Morny 的{@link MornyTrusted 信任验证机}
+ *
+ * @return {@link #trusted MornyCoeur.trusted}
+ */
+ @Nonnull
+ public static MornyTrusted trustedInstance () {
+ return INSTANCE.trusted;
}
}
diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyTrusted.java b/src/main/java/cc/sukazyo/cono/morny/MornyTrusted.java
index c2a07de..f892b9d 100644
--- a/src/main/java/cc/sukazyo/cono/morny/MornyTrusted.java
+++ b/src/main/java/cc/sukazyo/cono/morny/MornyTrusted.java
@@ -12,13 +12,18 @@ public class MornyTrusted {
* 群聊id,其指向的群聊指示了哪个群的成员是受信任的
* @see #isTrusted(long) 受信检查
*/
- public static final long TRUSTED_CHAT_ID = -1001541451710L;
+ public final Long TRUSTED_CHAT_ID;
/**
* morny 的主人
* 这项值的对象总是会被认为是可信任的
*/
- public static final long MASTER = 793274677L;
+ public final long MASTER;
+
+ public MornyTrusted (long master, long trustedChatId) {
+ this.TRUSTED_CHAT_ID = trustedChatId;
+ this.MASTER = master;
+ }
/**
* 用于检查一个 telegram-user 是否受信任
@@ -30,7 +35,7 @@ public class MornyTrusted {
* @param userId 需要检查的用户的id
* @return 所传递的用户id对应的用户是否受信任
*/
- public static boolean isTrusted (long userId) {
+ public boolean isTrusted (long userId) {
if (userId == MASTER) return true;
final ChatMember chatMember = MornyCoeur.getAccount().execute(new GetChatMember(TRUSTED_CHAT_ID, userId)).chatMember();
return (
diff --git a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java
index 78f1702..fcbe489 100644
--- a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java
+++ b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java
@@ -59,7 +59,7 @@ public class ServerMain {
* 但实际上这并不影响现在的使用,选项赋值目前仍属于测试功能
* 但请勿混用,这将使两个赋值出现混淆并产生不可知的结果
*
- * @see MornyCoeur#main(String, String, long)
+ * @see MornyCoeur#main(String, String, long, long, long)
* @since 0.4.0.0
* @param args 参数组
*/
@@ -68,6 +68,8 @@ public class ServerMain {
String key = null;
String username = null;
boolean outdatedBlock = false;
+ long master = 793274677L;
+ long trustedChat = -1001541451710L;
for (int i = 0; i < args.length; i++) {
@@ -100,6 +102,16 @@ public class ServerMain {
username = args[i];
continue;
}
+ case "--master" -> {
+ i++;
+ master = Long.parseLong(args[i]);
+ continue;
+ }
+ case "--trusted-chat" -> {
+ i++;
+ trustedChat = Long.parseLong(args[i]);
+ continue;
+ }
}
} else {
@@ -143,7 +155,7 @@ public class ServerMain {
if (welcomeEchoMode) return;
assert key != null;
- MornyCoeur.main(key, username, outdatedBlock?System.currentTimeMillis():0);
+ MornyCoeur.main(key, username, master, trustedChat, outdatedBlock?System.currentTimeMillis():0);
}
diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java
index c1c14e0..6d10041 100644
--- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java
+++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCallMe.java
@@ -23,7 +23,7 @@ public class OnCallMe extends EventListener {
* 跟随 {@link MornyTrusted#MASTER} 的值
* @since 0.4.2.1
*/
- private static final long ME = MornyTrusted.MASTER;
+ private static final long ME = MornyCoeur.trustedInstance().MASTER;
/**
* 监听私聊 bot 的消息进行呼叫关键字匹配。
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
index 5f5da75..3090192 100644
--- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java
+++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnCommandExecute.java
@@ -3,7 +3,6 @@ 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.MornyTrusted;
import cc.sukazyo.cono.morny.bot.api.EventListener;
import cc.sukazyo.cono.morny.bot.api.InputCommand;
import cc.sukazyo.cono.morny.bot.event.on_commands.EventHack;
@@ -88,7 +87,7 @@ public class OnCommandExecute extends EventListener {
}
private void onCommandExitExec (@Nonnull Update event) {
- if (MornyTrusted.isTrusted(event.message().from().id())) {
+ if (MornyCoeur.trustedInstance().isTrusted(event.message().from().id())) {
MornyCoeur.getAccount().execute(new SendSticker(
event.message().chat().id(),
TelegramStickers.ID_EXIT
diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java
index 3f7068b..4b96284 100644
--- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java
+++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnUpdateTimestampOffsetLock.java
@@ -17,30 +17,41 @@ import javax.annotation.Nonnull;
*