Auto-register scheduled messages event in Cronicle on startup
On startup raggr calls the Cronicle API (CRONICLE_URL + CRONICLE_API_KEY) and creates a 'Scheduled Messages Trigger' shell event if it doesn't exist, replacing the need to configure it manually in the Cronicle UI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -125,6 +125,12 @@ GOOGLE_TOKEN_FILE=/app/config/google-token.json
|
||||
# Shared secret for Cronicle to authenticate cron job trigger requests.
|
||||
# Generate with: openssl rand -hex 32
|
||||
CRON_SECRET=
|
||||
# Cronicle server URL and API key (from Cronicle Admin → API Keys)
|
||||
# Used to auto-register scheduled jobs on startup.
|
||||
CRONICLE_URL=http://cronicle:3012
|
||||
CRONICLE_API_KEY=
|
||||
# Internal URL raggr is reachable at from within the Cronicle container
|
||||
RAGGR_INTERNAL_URL=http://raggr-green:8080
|
||||
|
||||
# SimbaKit / PetKit Configuration
|
||||
# PetKit account credentials (used by SimbaKit to poll device data)
|
||||
|
||||
@@ -106,6 +106,10 @@ async def lifespan():
|
||||
app.main_agent = build_agent(checkpointer)
|
||||
logging.info(f"Agent checkpointer ready at {checkpoint_path}")
|
||||
|
||||
from utils.cronicle import ensure_cronicle_events
|
||||
|
||||
await ensure_cronicle_events()
|
||||
|
||||
watcher_task = None
|
||||
if os.getenv("OBSIDIAN_CONTINUOUS_SYNC") == "true":
|
||||
watcher_task = asyncio.create_task(_obsidian_sync_loop())
|
||||
|
||||
@@ -61,6 +61,9 @@ x-raggr-common: &raggr-common
|
||||
- ALLOWED_IMESSAGE_NUMBERS=${ALLOWED_IMESSAGE_NUMBERS}
|
||||
- SIMBAKIT_URL=${SIMBAKIT_URL:-http://simbakit:8585}
|
||||
- CRON_SECRET=${CRON_SECRET}
|
||||
- CRONICLE_URL=${CRONICLE_URL:-http://cronicle:3012}
|
||||
- CRONICLE_API_KEY=${CRONICLE_API_KEY}
|
||||
- RAGGR_INTERNAL_URL=${RAGGR_INTERNAL_URL:-http://raggr-green:8080}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import httpx
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_SCHEDULED_MESSAGES_TITLE = "Scheduled Messages Trigger"
|
||||
|
||||
|
||||
def _base_url() -> str:
|
||||
return os.environ.get("CRONICLE_URL", "").rstrip("/")
|
||||
|
||||
|
||||
def _api_key() -> str:
|
||||
return os.environ.get("CRONICLE_API_KEY", "")
|
||||
|
||||
|
||||
async def _get_events() -> list[dict]:
|
||||
async with httpx.AsyncClient() as client:
|
||||
resp = await client.get(
|
||||
f"{_base_url()}/api/app/get_schedule/v1",
|
||||
params={"api_key": _api_key(), "limit": 100},
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
if data.get("code") != 0:
|
||||
raise RuntimeError(f"Cronicle get_schedule error: {data}")
|
||||
return data.get("rows", [])
|
||||
|
||||
|
||||
async def _create_event(title: str, script: str) -> str:
|
||||
async with httpx.AsyncClient() as client:
|
||||
resp = await client.post(
|
||||
f"{_base_url()}/api/app/create_event/v1",
|
||||
json={
|
||||
"api_key": _api_key(),
|
||||
"title": title,
|
||||
"enabled": 1,
|
||||
"plugin": "shellplug",
|
||||
"target": "allgrp",
|
||||
"category": "c_general",
|
||||
"timing": {},
|
||||
"params": {"script": script},
|
||||
"notes": "Auto-registered by raggr on startup",
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
if data.get("code") != 0:
|
||||
raise RuntimeError(f"Cronicle create_event error: {data}")
|
||||
return data["id"]
|
||||
|
||||
|
||||
async def ensure_cronicle_events() -> None:
|
||||
"""Ensure the scheduled messages trigger event exists in Cronicle.
|
||||
|
||||
Skips silently if CRONICLE_URL or CRONICLE_API_KEY are not set.
|
||||
"""
|
||||
if not _base_url() or not _api_key():
|
||||
logger.debug("CRONICLE_URL/CRONICLE_API_KEY not set — skipping registration")
|
||||
return
|
||||
|
||||
cron_secret = os.environ.get("CRON_SECRET", "")
|
||||
raggr_url = os.environ.get("RAGGR_INTERNAL_URL", "http://raggr-green:8080")
|
||||
|
||||
try:
|
||||
events = await _get_events()
|
||||
if any(e.get("title") == _SCHEDULED_MESSAGES_TITLE for e in events):
|
||||
logger.info("Cronicle: '%s' already registered", _SCHEDULED_MESSAGES_TITLE)
|
||||
return
|
||||
|
||||
script = (
|
||||
f"curl -sf -X POST {raggr_url}/api/scheduled-messages/trigger "
|
||||
f"-H 'X-Cron-Secret: {cron_secret}'"
|
||||
)
|
||||
event_id = await _create_event(_SCHEDULED_MESSAGES_TITLE, script)
|
||||
logger.info(
|
||||
"Cronicle: created '%s' (id=%s)", _SCHEDULED_MESSAGES_TITLE, event_id
|
||||
)
|
||||
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Cronicle registration failed — scheduled messages will not fire"
|
||||
)
|
||||
Reference in New Issue
Block a user