feat: add HTML template rendering and test notification functionality
Build and Deploy Docker Container / test (push) Successful in 32s
Build and Deploy Docker Container / build-and-deploy (push) Failing after 58s

This commit is contained in:
2026-05-10 12:01:25 +02:00
parent 1dcd80a8bb
commit 6bae1e2f66
4 changed files with 85 additions and 47 deletions
+46 -16
View File
@@ -10,6 +10,14 @@ import schedule
from dotenv import load_dotenv
from templates import load_templates
from dashboard import create_app
SCHEDULED_NOTIFICATIONS = [
(15, "reminder"),
(20, "420"),
(45, "reminder_halftime"),
(50, "halftime"),
]
TZDB_CACHE: dict | None = None
@@ -42,6 +50,15 @@ DISCORD_CHANNEL_ID = os.getenv('DISCORD_CHANNEL_ID')
GUILD_ID = os.getenv('DISCORD_GUILD_ID')
def get_state() -> dict:
with STATE_LOCK:
return dict(STATE)
def get_next_event() -> dict:
return get_next_scheduled_event()
def init_tzdb_cache() -> dict:
"""Initialize a cached lookup structure for tzdb data.
@@ -139,15 +156,8 @@ def get_next_scheduled_event(now: datetime | None = None) -> dict:
if now is None:
now = datetime.now()
schedule_map = [
(15, "reminder"),
(20, "420"),
(45, "reminder_halftime"),
(50, "halftime"),
]
candidates: list[tuple[datetime, str]] = []
for minute, msg_type in schedule_map:
for minute, msg_type in SCHEDULED_NOTIFICATIONS:
candidate = now.replace(minute=minute, second=0, microsecond=0)
if candidate > now:
candidates.append((candidate, msg_type))
@@ -155,8 +165,8 @@ def get_next_scheduled_event(now: datetime | None = None) -> dict:
if not candidates:
base = (now + timedelta(hours=1)).replace(minute=0,
second=0, microsecond=0)
next_dt = base.replace(minute=schedule_map[0][0])
return {"at": next_dt, "type": schedule_map[0][1]}
next_dt = base.replace(minute=SCHEDULED_NOTIFICATIONS[0][0])
return {"at": next_dt, "type": SCHEDULED_NOTIFICATIONS[0][1]}
next_dt, next_type = min(candidates, key=lambda x: x[0])
return {"at": next_dt, "type": next_type}
@@ -706,15 +716,33 @@ def where_is_it_420(
return results
def schedule_notification(interval: str, at: str, type: str) -> None:
"""Example: schedule.every().hour.at(":15").do(send_notification, "reminder")"""
if interval == "hour":
schedule.every().hour.at(at).do(send_notification, type)
elif interval == "day":
schedule.every().day.at(at).do(send_notification, type)
else:
logging.error(f"Unsupported interval: {interval}")
def start_dashboard() -> None:
"""Compatibility hook for tests and optional dashboard startup."""
app = create_app(get_state=get_state, get_next_event=get_next_event)
app.run(host="127.0.0.1", port=8080, debug=False, use_reloader=False)
def main() -> None:
"""
Main function to run the scheduler.
"""
# Schedule notifications
schedule.every().hour.at(":15").do(send_notification, "reminder")
schedule.every().hour.at(":20").do(send_notification, "420")
# schedule.every().hour.at(":45").do(send_notification, "reminder_halftime")
# schedule.every().hour.at(":50").do(send_notification, "halftime")
# Start the dashboard in a separate thread
dashboard_thread = threading.Thread(target=start_dashboard, daemon=True)
dashboard_thread.start()
# Schedule notifications based on the defined SCHEDULED_NOTIFICATIONS
for minute, msg_type in SCHEDULED_NOTIFICATIONS:
schedule_notification("hour", f":{minute:02d}", msg_type)
# Schedule deletion of old messages every 5 minutes
schedule.every(5).minutes.do(delete_old_messages, 6)
@@ -722,7 +750,9 @@ def main() -> None:
logging.info("Scheduler started.")
# Test the notification on startup
# send_notification("420")
send_notification("test")
# delete the test message after a short delay to keep the channel clean
schedule.every(1).minutes.do(delete_old_messages, 1)
# delete old messages on startup to clean up any previous notifications
# delete_old_messages(6)