added api

This commit is contained in:
2026-06-10 10:29:21 +03:00
parent d0bdd1e95c
commit 73baf4dbe1
26 changed files with 1201 additions and 6 deletions
+130
View File
@@ -0,0 +1,130 @@
import asyncio
import logging
import random
from datetime import datetime
from zoneinfo import ZoneInfo
from app.config import get_settings
from app.db.base import SessionLocal
from app.homelab.comfyui import ComfyUIClient
from app.homelab.context import resolve_timezone
from app.homelab.digest import build_morning_digest
from app.homelab.monitoring import check_netdata_alerts
from app.homelab.notices import post_chat_notice
from app.homelab.state import get_state, set_state
logger = logging.getLogger(__name__)
WATCH_INTERVAL_SEC = 60
_netdata_tick = 0
async def homelab_watcher_loop() -> None:
global _netdata_tick
while True:
try:
await asyncio.sleep(WATCH_INTERVAL_SEC)
await _tick_morning_digest()
await _tick_rofl()
settings = get_settings()
_netdata_tick += WATCH_INTERVAL_SEC
if _netdata_tick >= settings.netdata_poll_interval_sec:
_netdata_tick = 0
await _tick_netdata()
except asyncio.CancelledError:
raise
except Exception:
logger.exception("Homelab watcher error")
async def _tick_morning_digest() -> None:
settings = get_settings()
if not settings.morning_digest_enabled:
return
db = SessionLocal()
try:
tz_name = resolve_timezone(db)
try:
tz = ZoneInfo(tz_name)
except Exception:
tz = ZoneInfo("Europe/Moscow")
now = datetime.now(tz)
target_min = settings.morning_digest_hour * 60 + settings.morning_digest_minute
current_min = now.hour * 60 + now.minute
if current_min < target_min or current_min >= target_min + 3:
return
today = now.date().isoformat()
if get_state(db, "last_morning_digest_date") == today:
return
digest = build_morning_digest(db, include_news=True)
post_chat_notice(digest)
set_state(db, "last_morning_digest_date", today)
finally:
db.close()
async def _tick_netdata() -> None:
db = SessionLocal()
try:
for notice in check_netdata_alerts(db):
post_chat_notice(notice)
finally:
db.close()
async def _tick_rofl() -> None:
settings = get_settings()
if not settings.comfyui_enabled or not settings.comfyui_rofl_enabled:
return
db = SessionLocal()
try:
tz_name = resolve_timezone(db)
try:
tz = ZoneInfo(tz_name)
except Exception:
tz = ZoneInfo("Europe/Moscow")
now = datetime.now(tz)
last_raw = get_state(db, "last_comfy_rofl_at")
if last_raw:
try:
last_at = datetime.fromisoformat(last_raw)
if last_at.tzinfo is None:
last_at = last_at.replace(tzinfo=tz)
if (now - last_at).total_seconds() < settings.comfyui_rofl_min_interval_hours * 3600:
return
except ValueError:
pass
if random.random() > settings.comfyui_rofl_probability:
return
today = now.date().isoformat()
count_raw = get_state(db, f"comfy_rofl_count_{today}") or "0"
try:
count = int(count_raw)
except ValueError:
count = 0
if count >= settings.comfyui_rofl_max_per_day:
return
client = ComfyUIClient()
prompt = client.random_rofl_prompt()
result = await client.generate_image(prompt)
if not result.get("ok"):
logger.warning("Rofl image failed: %s", result.get("error"))
return
url = result.get("url", "")
post_chat_notice(
f"🎨 **Рофл дня**\n\n![rofl]({url})\n\n_{prompt}_"
)
set_state(db, f"comfy_rofl_count_{today}", str(count + 1))
set_state(db, "last_comfy_rofl_at", now.isoformat())
finally:
db.close()