import json import uuid import httpx from typing import Optional from .config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, TELEGRAM_WEBHOOK_URL from .db import save_telegram_callback, get_telegram_callback, mark_telegram_responded _BASE = "https://api.telegram.org/bot" def _enabled() -> bool: return bool(TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID) async def _api(method: str, payload: dict) -> dict: if not _enabled(): return {"ok": False, "description": "Telegram not configured"} async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.post(f"{_BASE}{TELEGRAM_BOT_TOKEN}/{method}", json=payload) return resp.json() async def send_message(text: str, reply_markup: dict = None) -> dict: payload = { "chat_id": TELEGRAM_CHAT_ID, "text": text, "parse_mode": "HTML", } if reply_markup: payload["reply_markup"] = reply_markup result = await _api("sendMessage", payload) return { "ok": result.get("ok", False), "message_id": result.get("result", {}).get("message_id") if result.get("ok") else None, } async def send_stock_summary(summary: str) -> dict: return await send_message(summary) async def send_approval_request(agent_id: str, task_id: str, title: str, detail: str) -> dict: approve_id = f"approve_{uuid.uuid4().hex[:8]}" reject_id = f"reject_{uuid.uuid4().hex[:8]}" save_telegram_callback(approve_id, task_id, agent_id) save_telegram_callback(reject_id, task_id, agent_id) text = f"{title}\n{'━' * 20}\n{detail}" reply_markup = { "inline_keyboard": [[ {"text": "✅ 승인", "callback_data": approve_id}, {"text": "❌ 거절", "callback_data": reject_id}, ]] } return await send_message(text, reply_markup) async def send_task_result(agent_id: str, title: str, result: str) -> dict: text = f"{title}\n{'━' * 20}\n{result}" return await send_message(text) async def handle_webhook(data: dict) -> Optional[dict]: callback_query = data.get("callback_query") if not callback_query: return None callback_id = callback_query.get("data", "") cb = get_telegram_callback(callback_id) if not cb: return None action = "approve" if callback_id.startswith("approve_") else "reject" mark_telegram_responded(callback_id, action) await _api("answerCallbackQuery", { "callback_query_id": callback_query["id"], "text": "승인됨 ✅" if action == "approve" else "거절됨 ❌", }) return { "task_id": cb["task_id"], "agent_id": cb["agent_id"], "action": action, "approved": action == "approve", } async def setup_webhook() -> dict: if not _enabled() or not TELEGRAM_WEBHOOK_URL: return {"ok": False, "description": "Webhook URL not configured"} return await _api("setWebhook", {"url": TELEGRAM_WEBHOOK_URL})