diff --git a/gradle.properties b/gradle.properties index 1ab81d9..d18bae9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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-RC2.1 +VERSION = 1.0.0-RC3 USE_DELTA = false VERSION_DELTA = diff --git a/src/main/java/cc/sukazyo/cono/morny/MornyConfig.java b/src/main/java/cc/sukazyo/cono/morny/MornyConfig.java index be61e15..bdc8893 100644 --- a/src/main/java/cc/sukazyo/cono/morny/MornyConfig.java +++ b/src/main/java/cc/sukazyo/cono/morny/MornyConfig.java @@ -3,6 +3,7 @@ package cc.sukazyo.cono.morny; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.lang.annotation.*; +import java.time.ZoneOffset; import java.util.HashSet; import java.util.Set; @@ -114,6 +115,16 @@ public class MornyConfig { @Nonnull public final Set dinnerTrustedReaders; public final long dinnerChatId; + /* ======================================= * + * function: medication timer * + * ======================================= */ + + public final long medicationNotifyToChat; + + @Nonnull public final ZoneOffset medicationTimerUseTimezone; + + @Nonnull public final Set medicationNotifyAt; + /* ======================================= * * End Configs | ConfigBuilder * * ======================================= */ @@ -134,11 +145,16 @@ public class MornyConfig { this.dinnerTrustedReaders = prototype.dinnerTrustedReaders; this.dinnerChatId = prototype.dinnerChatId; this.reportToChat = prototype.reportToChat; + this.medicationNotifyToChat = prototype.medicationNotifyToChat; + this.medicationTimerUseTimezone = prototype.medicationTimerUseTimezone; + prototype.medicationNotifyAt.forEach(i -> { if (i < 0 || i > 23) throw new CheckFailure.UnavailableTimeInMedicationNotifyAt(); }); + this.medicationNotifyAt = prototype.medicationNotifyAt; } - public static class CheckFailure extends Exception { + public static class CheckFailure extends RuntimeException { public static class NullTelegramBotKey extends CheckFailure {} public static class UnsetEventOutdatedTimestamp extends CheckFailure {} + public static class UnavailableTimeInMedicationNotifyAt extends CheckFailure {} } public static class Prototype { @@ -156,6 +172,9 @@ public class MornyConfig { @Nonnull public Set dinnerTrustedReaders = new HashSet<>(); public long dinnerChatId = -1001707106392L; public long reportToChat = -1001650050443L; + public long medicationNotifyToChat = -1001729016815L; + @Nonnull public ZoneOffset medicationTimerUseTimezone = ZoneOffset.UTC; + @Nonnull public Set medicationNotifyAt = new HashSet<>(); } diff --git a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java index e9237ee..ba8e79e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/ServerMain.java +++ b/src/main/java/cc/sukazyo/cono/morny/ServerMain.java @@ -4,6 +4,8 @@ import cc.sukazyo.cono.morny.util.CommonFormat; import javax.annotation.Nonnull; +import java.time.ZoneOffset; + import static cc.sukazyo.cono.morny.Log.logger; /** @@ -166,6 +168,22 @@ public class ServerMain { config.reportToChat = Long.parseLong(args[i]); continue; } + case "--medication-notify-chat", "-medc" -> { + i++; + config.medicationNotifyToChat = Long.parseLong(args[i]); + continue; + } + case "--medication-notify-timezone", "-medtz" -> { + i++; + config.medicationTimerUseTimezone = ZoneOffset.ofHours(Integer.parseInt(args[i])); + continue; + } + case "--medication-notify-times", "-medt" -> { + i++; + for (String u : args[i].split(",")) + config.medicationNotifyAt.add(Integer.parseInt(u)); + continue; + } } } diff --git a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java index a5bd835..7217635 100644 --- a/src/main/java/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java +++ b/src/main/java/cc/sukazyo/cono/morny/bot/event/OnMedicationNotifyApply.java @@ -1,7 +1,7 @@ package cc.sukazyo.cono.morny.bot.event; +import cc.sukazyo.cono.morny.MornyCoeur; import cc.sukazyo.cono.morny.bot.api.EventListener; -import cc.sukazyo.cono.morny.daemon.MedicationTimer; import cc.sukazyo.cono.morny.daemon.MornyDaemons; import com.pengrad.telegrambot.model.Message; import com.pengrad.telegrambot.model.Update; @@ -20,7 +20,7 @@ public class OnMedicationNotifyApply extends EventListener { } private boolean editedMessageProcess (Message edited) { - if (edited.chat().id() != MedicationTimer.NOTIFY_CHAT) return false; + if (edited.chat().id() != MornyCoeur.config().medicationNotifyToChat) return false; MornyDaemons.medicationTimerInstance.refreshNotificationWrite(edited); return true; } diff --git a/src/main/java/cc/sukazyo/cono/morny/daemon/MedicationTimer.java b/src/main/java/cc/sukazyo/cono/morny/daemon/MedicationTimer.java index dec57fa..6760b4e 100644 --- a/src/main/java/cc/sukazyo/cono/morny/daemon/MedicationTimer.java +++ b/src/main/java/cc/sukazyo/cono/morny/daemon/MedicationTimer.java @@ -20,15 +20,16 @@ import static cc.sukazyo.cono.morny.Log.logger; public class MedicationTimer extends Thread { - public static final ZoneOffset USE_TIME_ZONE = ZoneOffset.ofHours(8); - public static final Set NOTIFY_AT_HOUR = Set.of(12); - public static final long NOTIFY_CHAT = -1001729016815L; + private final ZoneOffset USE_TIME_ZONE = MornyCoeur.config().medicationTimerUseTimezone; + private final Set NOTIFY_AT_HOUR = MornyCoeur.config().medicationNotifyAt; + private final long NOTIFY_CHAT = MornyCoeur.config().medicationNotifyToChat; public static final String NOTIFY_MESSAGE = "\uD83C\uDF65⏲"; private static final String DAEMON_THREAD_NAME = "TIMER_Medication"; private static final long LAST_NOTIFY_ID_NULL = -1L; private long lastNotify = LAST_NOTIFY_ID_NULL; + public static class NoNotifyTimeTag extends Throwable { private NoNotifyTimeTag(){} } MedicationTimer () { super(DAEMON_THREAD_NAME); @@ -44,6 +45,9 @@ public class MedicationTimer extends Thread { } catch (InterruptedException e) { interrupt(); logger.info("MedicationTimer was interrupted, will be exit now"); + } catch (NoNotifyTimeTag ignored) { + logger.warn("Notify Time not Set and the MedicationTimer will not working!\nMedicationTimer will be exit now."); + interrupt(); } catch (Exception e) { logger.error("Unexpected error occurred"); logger.error(exceptionLog(e)); @@ -74,9 +78,11 @@ public class MedicationTimer extends Thread { lastNotify = LAST_NOTIFY_ID_NULL; } - public static long calcNextRoutineTimestamp (long baseTimeMillis, ZoneOffset useTimeZone, Set atHours) { + public static long calcNextRoutineTimestamp (long baseTimeMillis, ZoneOffset useTimeZone, Set atHours) + throws NoNotifyTimeTag { + if (atHours.isEmpty()) throw new NoNotifyTimeTag(); LocalDateTime time = LocalDateTime.ofEpochSecond( - baseTimeMillis/1000, (int)baseTimeMillis%1000*1000, + baseTimeMillis/1000, (int)(baseTimeMillis%1000)*1000*1000, useTimeZone ).withMinute(0).withSecond(0).withNano(0); do { @@ -85,7 +91,7 @@ public class MedicationTimer extends Thread { return time.withMinute(0).withSecond(0).withNano(0).toInstant(useTimeZone).toEpochMilli(); } - private void waitToNextRoutine () throws InterruptedException { + private void waitToNextRoutine () throws InterruptedException, NoNotifyTimeTag { sleep(calcNextRoutineTimestamp(System.currentTimeMillis(), USE_TIME_ZONE, NOTIFY_AT_HOUR) - System.currentTimeMillis()); } diff --git a/src/test/java/cc/sukazyo/cono/morny/daemon/TestMedicationTimer.java b/src/test/java/cc/sukazyo/cono/morny/daemon/TestMedicationTimer.java index cb74065..58600ce 100644 --- a/src/test/java/cc/sukazyo/cono/morny/daemon/TestMedicationTimer.java +++ b/src/test/java/cc/sukazyo/cono/morny/daemon/TestMedicationTimer.java @@ -12,18 +12,23 @@ public class TestMedicationTimer { @ParameterizedTest @CsvSource(textBlock = """ - 2022-11-13T13:14:35+08, +08, 2022-11-14T12:00:00+08 - 2022-11-13T13:14:35+02, +02, 2022-11-14T12:00:00+02 - 2022-11-13T08:14:35+08, +08, 2022-11-13T12:00:00+08 - 2022-11-13T00:14:35+08, +08, 2022-11-13T12:00:00+08 - 2022-11-13T12:00:00+00, +00, 2022-11-14T12:00:00+00 + 2022-11-13T13:14:35.000+08, +08, 2022-11-13T19:00:00+08 + 2022-11-13T13:14:35.174+02, +02, 2022-11-13T19:00:00+02 + 1998-02-01T08:14:35.871+08, +08, 1998-02-01T19:00:00+08 + 2022-11-13T00:00:00.000-01, -01, 2022-11-13T07:00:00-01 + 2022-11-21T19:00:00.000+00, +00, 2022-11-21T21:00:00+00 + 2022-12-31T21:00:00.000+00, +00, 2023-01-01T07:00:00+00 + 2125-11-18T23:45:27.062+00, +00, 2125-11-19T07:00:00+00 """) - void testCalcNextRoutineTimestamp (ZonedDateTime base, ZoneOffset zoneHour, ZonedDateTime expected) { - final Set at = Set.of(12); + void testCalcNextRoutineTimestamp (ZonedDateTime base, ZoneOffset zoneHour, ZonedDateTime expected) + throws MedicationTimer.NoNotifyTimeTag { + final Set at = Set.of(7, 19, 21); + System.out.println("base.toInstant().toEpochMilli() = " + base.toInstant().toEpochMilli()); Assertions.assertEquals( - expected.toEpochSecond()*1000, - MedicationTimer.calcNextRoutineTimestamp(base.toEpochSecond()*1000, zoneHour, at) + expected.toInstant().toEpochMilli(), + MedicationTimer.calcNextRoutineTimestamp(base.toInstant().toEpochMilli(), zoneHour, at) ); + System.out.println(" ok"); } }