Files
Home_assistant/telegram-bot/bot/notify_worker.py
T
2026-06-14 06:26:16 +00:00

128 lines
4.0 KiB
Python

from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from aiogram import Bot
from bot.ha_client import HaClient
from bot.notice_delivery import send_notice_content
from bot.storage import LinkedUser, Storage
if TYPE_CHECKING:
pass
logger = logging.getLogger(__name__)
NOTICE_ROLES = frozenset({"notice", "character"})
async def advance_cursors(
storage: Storage,
client: HaClient,
user: LinkedUser,
) -> None:
sessions = await client.list_sessions()
for session in sessions:
session_id = int(session["id"])
after_id = await storage.get_last_message_id(user.telegram_id, session_id)
page = await client.get_messages(session_id, after_id=after_id or None, limit=100)
messages = page.get("messages") or []
max_id = after_id
for message in messages:
msg_id = int(message["id"])
max_id = max(max_id, msg_id)
if max_id > after_id:
await storage.set_last_message_id(user.telegram_id, session_id, max_id)
async def sync_notices_for_user(
bot: Bot,
storage: Storage,
ha_base_url: str,
user: LinkedUser,
*,
send: bool = True,
) -> None:
client = HaClient(ha_base_url, user.api_token)
try:
reminders = await client.get_reminders_snapshot()
pomodoro = await client.get_pomodoro_status()
except Exception:
logger.exception("Failed to fetch notify seq for telegram_id=%s", user.telegram_id)
reminders = {}
pomodoro = {}
reminder_seq = int(reminders.get("notify_seq") or 0)
pomodoro_seq = int((pomodoro.get("cycle") or {}).get("chat_notify_seq") or 0)
sessions = await client.list_sessions()
pending: list[tuple[int, str]] = []
for session in sessions:
session_id = int(session["id"])
after_id = await storage.get_last_message_id(user.telegram_id, session_id)
try:
page = await client.get_messages(session_id, after_id=after_id or None, limit=100)
except Exception:
logger.exception(
"Failed to fetch messages session_id=%s telegram_id=%s",
session_id,
user.telegram_id,
)
continue
messages = page.get("messages") or []
max_id = after_id
for message in messages:
msg_id = int(message["id"])
max_id = max(max_id, msg_id)
role = str(message.get("role") or "")
if role in NOTICE_ROLES and send:
content = str(message.get("content") or "").strip()
if content:
pending.append((msg_id, content))
if max_id > after_id:
await storage.set_last_message_id(user.telegram_id, session_id, max_id)
if send:
pending.sort(key=lambda item: item[0])
for _, content in pending:
try:
await send_notice_content(
bot,
user.telegram_id,
content,
client,
ha_api_base=ha_base_url,
)
except Exception:
logger.exception("Failed to send notice to telegram_id=%s", user.telegram_id)
await storage.update_seq(
user.telegram_id,
reminder_seq=reminder_seq,
pomodoro_seq=pomodoro_seq,
)
async def run_notify_worker(
bot: Bot,
storage: Storage,
ha_base_url: str,
poll_interval_sec: int,
) -> None:
import asyncio
logger.info("Notify worker started (interval=%ss)", poll_interval_sec)
while True:
users = await storage.list_linked_users()
for user in users:
try:
await sync_notices_for_user(bot, storage, ha_base_url, user, send=True)
except Exception:
logger.exception("Notify sync failed for telegram_id=%s", user.telegram_id)
await asyncio.sleep(poll_interval_sec)