mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-26 13:07:40 +08:00
add -medc/medt/medtz params and configs for customize MedicationTimer status, fix millis/nanos conv problem again
- add configs for medication timer - medicationNotifyToChat - default is -1001729016815L(Annie medication notify chat) - add param --medication-notify-chat / -medc to set it, accept a long number. - medicationTimerUseTimezone - default is ZoneOffset.UTC(means +00:00) - add param --medication-notify-timezone / -medtz to set it, accept a number that means timezone hours - medicationNotifyAt - default is a empty Set - add param --medication-notify-times / -medt to set it, accept a hour(0~23) list seperated by "," - now medication timer will exit if the notify-times is empty - changed the Test data-source for MedicationTimer#calcNextRoutineTimestamp
This commit is contained in:
parent
2ffab30ef1
commit
8e28bbbce1
@ -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-RC2.1
|
VERSION = 1.0.0-RC3
|
||||||
|
|
||||||
USE_DELTA = false
|
USE_DELTA = false
|
||||||
VERSION_DELTA =
|
VERSION_DELTA =
|
||||||
|
@ -3,6 +3,7 @@ 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.lang.annotation.*;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -114,6 +115,16 @@ public class MornyConfig {
|
|||||||
@Nonnull public final Set<Long> dinnerTrustedReaders;
|
@Nonnull public final Set<Long> dinnerTrustedReaders;
|
||||||
public final long dinnerChatId;
|
public final long dinnerChatId;
|
||||||
|
|
||||||
|
/* ======================================= *
|
||||||
|
* function: medication timer *
|
||||||
|
* ======================================= */
|
||||||
|
|
||||||
|
public final long medicationNotifyToChat;
|
||||||
|
|
||||||
|
@Nonnull public final ZoneOffset medicationTimerUseTimezone;
|
||||||
|
|
||||||
|
@Nonnull public final Set<Integer> medicationNotifyAt;
|
||||||
|
|
||||||
/* ======================================= *
|
/* ======================================= *
|
||||||
* End Configs | ConfigBuilder *
|
* End Configs | ConfigBuilder *
|
||||||
* ======================================= */
|
* ======================================= */
|
||||||
@ -134,11 +145,16 @@ public class MornyConfig {
|
|||||||
this.dinnerTrustedReaders = prototype.dinnerTrustedReaders;
|
this.dinnerTrustedReaders = prototype.dinnerTrustedReaders;
|
||||||
this.dinnerChatId = prototype.dinnerChatId;
|
this.dinnerChatId = prototype.dinnerChatId;
|
||||||
this.reportToChat = prototype.reportToChat;
|
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 NullTelegramBotKey extends CheckFailure {}
|
||||||
public static class UnsetEventOutdatedTimestamp extends CheckFailure {}
|
public static class UnsetEventOutdatedTimestamp extends CheckFailure {}
|
||||||
|
public static class UnavailableTimeInMedicationNotifyAt extends CheckFailure {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Prototype {
|
public static class Prototype {
|
||||||
@ -156,6 +172,9 @@ public class MornyConfig {
|
|||||||
@Nonnull public Set<Long> dinnerTrustedReaders = new HashSet<>();
|
@Nonnull public Set<Long> dinnerTrustedReaders = new HashSet<>();
|
||||||
public long dinnerChatId = -1001707106392L;
|
public long dinnerChatId = -1001707106392L;
|
||||||
public long reportToChat = -1001650050443L;
|
public long reportToChat = -1001650050443L;
|
||||||
|
public long medicationNotifyToChat = -1001729016815L;
|
||||||
|
@Nonnull public ZoneOffset medicationTimerUseTimezone = ZoneOffset.UTC;
|
||||||
|
@Nonnull public Set<Integer> medicationNotifyAt = new HashSet<>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ import cc.sukazyo.cono.morny.util.CommonFormat;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
import static cc.sukazyo.cono.morny.Log.logger;
|
import static cc.sukazyo.cono.morny.Log.logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,6 +168,22 @@ public class ServerMain {
|
|||||||
config.reportToChat = Long.parseLong(args[i]);
|
config.reportToChat = Long.parseLong(args[i]);
|
||||||
continue;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package cc.sukazyo.cono.morny.bot.event;
|
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.bot.api.EventListener;
|
||||||
import cc.sukazyo.cono.morny.daemon.MedicationTimer;
|
|
||||||
import cc.sukazyo.cono.morny.daemon.MornyDaemons;
|
import cc.sukazyo.cono.morny.daemon.MornyDaemons;
|
||||||
import com.pengrad.telegrambot.model.Message;
|
import com.pengrad.telegrambot.model.Message;
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
@ -20,7 +20,7 @@ public class OnMedicationNotifyApply extends EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean editedMessageProcess (Message edited) {
|
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);
|
MornyDaemons.medicationTimerInstance.refreshNotificationWrite(edited);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,16 @@ import static cc.sukazyo.cono.morny.Log.logger;
|
|||||||
|
|
||||||
public class MedicationTimer extends Thread {
|
public class MedicationTimer extends Thread {
|
||||||
|
|
||||||
public static final ZoneOffset USE_TIME_ZONE = ZoneOffset.ofHours(8);
|
private final ZoneOffset USE_TIME_ZONE = MornyCoeur.config().medicationTimerUseTimezone;
|
||||||
public static final Set<Integer> NOTIFY_AT_HOUR = Set.of(12);
|
private final Set<Integer> NOTIFY_AT_HOUR = MornyCoeur.config().medicationNotifyAt;
|
||||||
public static final long NOTIFY_CHAT = -1001729016815L;
|
private final long NOTIFY_CHAT = MornyCoeur.config().medicationNotifyToChat;
|
||||||
public static final String NOTIFY_MESSAGE = "\uD83C\uDF65⏲";
|
public static final String NOTIFY_MESSAGE = "\uD83C\uDF65⏲";
|
||||||
private static final String DAEMON_THREAD_NAME = "TIMER_Medication";
|
private static final String DAEMON_THREAD_NAME = "TIMER_Medication";
|
||||||
|
|
||||||
private static final long LAST_NOTIFY_ID_NULL = -1L;
|
private static final long LAST_NOTIFY_ID_NULL = -1L;
|
||||||
private long lastNotify = LAST_NOTIFY_ID_NULL;
|
private long lastNotify = LAST_NOTIFY_ID_NULL;
|
||||||
|
|
||||||
|
public static class NoNotifyTimeTag extends Throwable { private NoNotifyTimeTag(){} }
|
||||||
|
|
||||||
MedicationTimer () {
|
MedicationTimer () {
|
||||||
super(DAEMON_THREAD_NAME);
|
super(DAEMON_THREAD_NAME);
|
||||||
@ -44,6 +45,9 @@ public class MedicationTimer extends Thread {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
interrupt();
|
interrupt();
|
||||||
logger.info("MedicationTimer was interrupted, will be exit now");
|
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) {
|
} catch (Exception e) {
|
||||||
logger.error("Unexpected error occurred");
|
logger.error("Unexpected error occurred");
|
||||||
logger.error(exceptionLog(e));
|
logger.error(exceptionLog(e));
|
||||||
@ -74,9 +78,11 @@ public class MedicationTimer extends Thread {
|
|||||||
lastNotify = LAST_NOTIFY_ID_NULL;
|
lastNotify = LAST_NOTIFY_ID_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long calcNextRoutineTimestamp (long baseTimeMillis, ZoneOffset useTimeZone, Set<Integer> atHours) {
|
public static long calcNextRoutineTimestamp (long baseTimeMillis, ZoneOffset useTimeZone, Set<Integer> atHours)
|
||||||
|
throws NoNotifyTimeTag {
|
||||||
|
if (atHours.isEmpty()) throw new NoNotifyTimeTag();
|
||||||
LocalDateTime time = LocalDateTime.ofEpochSecond(
|
LocalDateTime time = LocalDateTime.ofEpochSecond(
|
||||||
baseTimeMillis/1000, (int)baseTimeMillis%1000*1000,
|
baseTimeMillis/1000, (int)(baseTimeMillis%1000)*1000*1000,
|
||||||
useTimeZone
|
useTimeZone
|
||||||
).withMinute(0).withSecond(0).withNano(0);
|
).withMinute(0).withSecond(0).withNano(0);
|
||||||
do {
|
do {
|
||||||
@ -85,7 +91,7 @@ public class MedicationTimer extends Thread {
|
|||||||
return time.withMinute(0).withSecond(0).withNano(0).toInstant(useTimeZone).toEpochMilli();
|
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());
|
sleep(calcNextRoutineTimestamp(System.currentTimeMillis(), USE_TIME_ZONE, NOTIFY_AT_HOUR) - System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,18 +12,23 @@ public class TestMedicationTimer {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@CsvSource(textBlock = """
|
@CsvSource(textBlock = """
|
||||||
2022-11-13T13:14:35+08, +08, 2022-11-14T12:00:00+08
|
2022-11-13T13:14:35.000+08, +08, 2022-11-13T19:00:00+08
|
||||||
2022-11-13T13:14:35+02, +02, 2022-11-14T12:00:00+02
|
2022-11-13T13:14:35.174+02, +02, 2022-11-13T19:00:00+02
|
||||||
2022-11-13T08:14:35+08, +08, 2022-11-13T12:00:00+08
|
1998-02-01T08:14:35.871+08, +08, 1998-02-01T19:00:00+08
|
||||||
2022-11-13T00:14:35+08, +08, 2022-11-13T12:00:00+08
|
2022-11-13T00:00:00.000-01, -01, 2022-11-13T07:00:00-01
|
||||||
2022-11-13T12:00:00+00, +00, 2022-11-14T12:00:00+00
|
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) {
|
void testCalcNextRoutineTimestamp (ZonedDateTime base, ZoneOffset zoneHour, ZonedDateTime expected)
|
||||||
final Set<Integer> at = Set.of(12);
|
throws MedicationTimer.NoNotifyTimeTag {
|
||||||
|
final Set<Integer> at = Set.of(7, 19, 21);
|
||||||
|
System.out.println("base.toInstant().toEpochMilli() = " + base.toInstant().toEpochMilli());
|
||||||
Assertions.assertEquals(
|
Assertions.assertEquals(
|
||||||
expected.toEpochSecond()*1000,
|
expected.toInstant().toEpochMilli(),
|
||||||
MedicationTimer.calcNextRoutineTimestamp(base.toEpochSecond()*1000, zoneHour, at)
|
MedicationTimer.calcNextRoutineTimestamp(base.toInstant().toEpochMilli(), zoneHour, at)
|
||||||
);
|
);
|
||||||
|
System.out.println(" ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user