c9c75b6be3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
110 lines
3.4 KiB
Python
110 lines
3.4 KiB
Python
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 _get_first_category_id() -> str:
|
|
async with httpx.AsyncClient() as client:
|
|
resp = await client.get(
|
|
f"{_base_url()}/api/app/get_categories/v1",
|
|
params={"api_key": _api_key()},
|
|
timeout=10,
|
|
)
|
|
resp.raise_for_status()
|
|
data = resp.json()
|
|
if data.get("code") != 0:
|
|
raise RuntimeError(f"Cronicle get_categories error: {data}")
|
|
rows = data.get("rows", [])
|
|
if not rows:
|
|
raise RuntimeError("Cronicle has no categories configured")
|
|
return rows[0]["id"]
|
|
|
|
|
|
async def _create_event(title: str, script: str, category_id: 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": category_id,
|
|
"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", "")
|
|
|
|
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
|
|
|
|
trigger_cmd = (
|
|
"curl -sf -X POST {url}/api/scheduled-messages/trigger"
|
|
f" -H 'X-Cron-Secret: {cron_secret}'"
|
|
)
|
|
script = (
|
|
trigger_cmd.format(url="http://raggr-green:8080")
|
|
+ " || "
|
|
+ trigger_cmd.format(url="http://raggr-blue:8080")
|
|
)
|
|
category_id = await _get_first_category_id()
|
|
event_id = await _create_event(_SCHEDULED_MESSAGES_TITLE, script, category_id)
|
|
logger.info(
|
|
"Cronicle: created '%s' (id=%s)", _SCHEDULED_MESSAGES_TITLE, event_id
|
|
)
|
|
|
|
except Exception:
|
|
logger.exception(
|
|
"Cronicle registration failed — scheduled messages will not fire"
|
|
)
|