from __future__ import annotations import json import base64 import logging from typing import Any, Union, get_args, get_origin import httpx from pydantic import TypeAdapter from aiogram.client.session.base import BaseSession from aiogram.client.default import Default from aiogram.methods import TelegramMethod from aiogram.methods.base import TelegramType from .config import settings logger = logging.getLogger(__name__) def _strip_defaults(obj): if isinstance(obj, Default): return None if isinstance(obj, dict): return {k: _strip_defaults(v) for k, v in obj.items() if not isinstance(v, Default)} if isinstance(obj, (list, tuple)): return [_strip_defaults(i) for i in obj] return obj class SupabaseProxySession(BaseSession): def __init__(self): super().__init__() self._client = httpx.AsyncClient(timeout=60) async def close(self): await self._client.aclose() async def make_request( self, bot, method: TelegramMethod[TelegramType], **kwargs: Any, ) -> TelegramType: url = f"{settings.SUPABASE_URL}/functions/v1/telegram-proxy" headers = { "Authorization": f"Bearer {settings.SUPABASE_SERVICE_KEY}", "x-bot-token": settings.TELEGRAM_BOT_TOKEN, "Content-Type": "application/json", } method_name = method.__api_method__ raw = method.model_dump(exclude_none=True) data = _strip_defaults(raw) body = {"method": method_name, "data": data} logger.info(f"Proxy → {method_name}") try: resp = await self._client.post(url, json=body, headers=headers) except Exception: logger.exception(f"Proxy HTTP error for {method_name}") raise result = resp.json() logger.info(f"Proxy ← {method_name} ok={result.get('ok')}") if not result.get("ok"): logger.error(f"Telegram API error for {method_name}: {result}") raise Exception(f"Telegram API error: {result}") ret_type = method.__returning__ if ret_type is bool: return result.get("result", True) try: return ret_type.model_validate(result["result"]) except Exception: ta = TypeAdapter(ret_type) return ta.validate_python(result["result"]) async def stream_content(self, url: str, timeout: int = 30, **kwargs): async with httpx.AsyncClient() as client: resp = await client.get(url) return resp.content