使 MornyCoeur 和 MornyTrusted 对象封装,添加 master 和 trustedChat 定义参数

This commit is contained in:
A.C.Sukazyo Eyre 2021-12-22 00:43:56 +08:00
parent 6a5a23b6be
commit def7ee79c2
Signed by: Eyre_S
GPG Key ID: EFB47D98FE082FAD
9 changed files with 135 additions and 43 deletions

View File

@ -1,6 +1,6 @@
## Core
VERSION = 0.4.2.6
VERSION = 0.4.2.7
# dependencies

View File

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

View File

@ -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 账户的用户名<br>
* <br>
@ -28,36 +34,40 @@ public class MornyCoeur {
* 如果在登陆之前就定义了此字段则登陆代码会验证登陆的 bot username
* 是否与定义的 username 符合如果不符合则会报错
*/
private static String username;
private final String username;
/**
* morny 的事件忽略前缀时间<br>
* <br>
* {@link cc.sukazyo.cono.morny.bot.event.OnUpdateTimestampOffsetLock}
* 会根据这里定义的时间戳取消掉比此时间更早的事件链
*/
public static long latestEventTimestamp;
public long latestEventTimestamp;
/**
* morny 主程序启动时间<br>
* 用于统计数据
*/
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.");
}
/**
* 向外界暴露的 morny 初始化入口.
* <p>
* 如果 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();
account.setUpdatesListener(OnUpdate::onNormalUpdate);
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;
}
}

View File

@ -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 的主人<br>
* 这项值的对象总是会被认为是可信任的
*/
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 是否受信任<br>
@ -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 (

View File

@ -59,7 +59,7 @@ public class ServerMain {
* <s>但实际上这并不影响现在的使用选项赋值目前仍属于测试功能</s><br>
* <b>但请勿混用</b>这将使两个赋值出现混淆并<b>产生不可知的结果</b>
*
* @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);
}

View File

@ -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 的消息进行呼叫关键字匹配

View File

@ -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

View File

@ -17,30 +17,41 @@ import javax.annotation.Nonnull;
* <li>{@link EventListener#onChannelPost(Update) 收到频道消息}</li>
* <li>{@link EventListener#onEditedChannelPost(Update) 频道消息被更新}</li>
* </ul>
* @see #isOutdated 时间判断
*/
public class OnUpdateTimestampOffsetLock extends EventListener {
/**
* 检查传入时间是否在要求时间之前"过期".
* @param timestamp 传入时间秒级
* @return 如果传入时间在要求时间<u>之前</u>返回true反之false
* @since 0.4.2.7
*/
public boolean isOutdated(long timestamp) {
return timestamp < MornyCoeur.getLatestEventTimestamp()/1000;
}
@Override
public boolean onMessage (@NotNull Update update) {
return update.message().date() < MornyCoeur.latestEventTimestamp/1000;
return isOutdated(update.message().date());
}
/** @since 0.4.2.6 */
@Override
public boolean onEditedMessage (@Nonnull Update update) {
return update.editedMessage().editDate() < MornyCoeur.latestEventTimestamp/1000;
return isOutdated(update.editedMessage().editDate());
}
/** @since 0.4.2.6 */
@Override
public boolean onChannelPost (@Nonnull Update update) {
return update.channelPost().date() < MornyCoeur.latestEventTimestamp/1000;
return isOutdated(update.channelPost().date());
}
/** @since 0.4.2.6 */
@Override
public boolean onEditedChannelPost (@Nonnull Update update) {
return update.editedChannelPost().editDate() < MornyCoeur.latestEventTimestamp/1000;
return isOutdated(update.editedChannelPost().editDate());
}
}

View File

@ -36,7 +36,7 @@ public class EventHack {
switch (x_mode) {
case "any":
if (MornyTrusted.isTrusted(event.message().from().id())) {
if (MornyCoeur.trustedInstance().isTrusted(event.message().from().id())) {
OnEventHackHandle.registerHack(
event.message().messageId(),
event.message().from().id(),