| """ |
| app.py — Servidor FastAPI mínimo |
| ================================= |
| • Mantiene el Hugging Face Space activo (keepalive) |
| • Arranca el bot de Telegram con su propio event loop en un hilo separado |
| • Sin Google Drive ni OAuth — todo en Telegram |
| """ |
|
|
| import os |
| import asyncio |
| import threading |
| import logging |
| import pathlib |
|
|
| import uvicorn |
| from fastapi import FastAPI |
| from fastapi.responses import HTMLResponse |
|
|
| logging.basicConfig( |
| format="%(asctime)s | %(levelname)s | %(message)s", |
| level=logging.INFO |
| ) |
| log = logging.getLogger(__name__) |
|
|
| DATA_DIR = pathlib.Path(os.environ.get("DATA_DIR", "/home/user/app/data")) |
| DATA_DIR.mkdir(parents=True, exist_ok=True) |
|
|
| api = FastAPI(title="TelegramMediaBot") |
|
|
|
|
| @api.get("/", response_class=HTMLResponse) |
| async def root(): |
| token = os.environ.get("TELEGRAM_TOKEN", "") |
| if not token: |
| return HTMLResponse(""" |
| <html><head><style> |
| body{font-family:'Segoe UI',sans-serif;background:#1a1a2e;color:#e0e0ff; |
| display:flex;justify-content:center;align-items:center;height:100vh;margin:0} |
| .card{background:#16213e;border:1px solid #e94560;border-radius:16px; |
| padding:40px;max-width:480px;text-align:center} |
| h1{color:#e94560}code{background:#0f3460;padding:2px 8px;border-radius:4px} |
| p{color:#a0a0cc;font-size:.95rem} |
| </style></head><body> |
| <div class="card"> |
| <h1>⚠️ Falta TELEGRAM_TOKEN</h1> |
| <p>Agrega la variable <code>TELEGRAM_TOKEN</code> en<br> |
| <b>Settings → Variables and Secrets</b> y reinicia el Space.</p> |
| </div></body></html> |
| """) |
| return """ |
| <html><head><style> |
| body{font-family:'Segoe UI',sans-serif;background:#0f0f1a;color:#e0e0ff; |
| display:flex;justify-content:center;align-items:center;height:100vh;margin:0} |
| .card{background:#1a1a2e;border:1px solid #3a3a8e;border-radius:16px; |
| padding:40px;text-align:center;max-width:420px} |
| h1{font-size:2rem;margin-bottom:8px} |
| p{color:#9090bb;font-size:.95rem} |
| .badge{background:#2a2a5e;border-radius:8px;padding:8px 18px; |
| display:inline-block;margin-top:18px;font-size:.9rem} |
| .dot{width:10px;height:10px;background:#4cff80;border-radius:50%; |
| display:inline-block;margin-right:8px;animation:pulse 2s infinite} |
| @keyframes pulse{0%,100%{opacity:1}50%{opacity:.3}} |
| </style></head><body> |
| <div class="card"> |
| <h1>📱 TelegramMediaBot</h1> |
| <p>Tu galería personal en Telegram.<br>Fotos, videos, audios y álbumes.</p> |
| <div class="badge"><span class="dot"></span>Bot activo · Almacenamiento nativo Telegram</div> |
| </div></body></html> |
| """ |
|
|
|
|
| @api.get("/health") |
| async def health(): |
| token_ok = bool(os.environ.get("TELEGRAM_TOKEN")) |
| return {"status": "ok" if token_ok else "misconfigured", "telegram_token": token_ok} |
|
|
|
|
| def start_bot(): |
| """Crea su propio event loop en el hilo secundario y corre el bot.""" |
| import bot |
| loop = asyncio.new_event_loop() |
| asyncio.set_event_loop(loop) |
| try: |
| loop.run_until_complete(bot.main_async()) |
| except Exception as e: |
| log.exception(f"Error en el bot: {e}") |
| finally: |
| loop.close() |
|
|
|
|
| if __name__ == "__main__": |
| import bot as bot_module |
| bot_module.DB_PATH = str(DATA_DIR / "media.db") |
| bot_module.init_db() |
|
|
| if not os.environ.get("TELEGRAM_TOKEN"): |
| log.error("TELEGRAM_TOKEN no configurado — el bot no iniciara") |
| log.info("Servidor web activo igualmente para mostrar instrucciones") |
| else: |
| t = threading.Thread(target=start_bot, daemon=True) |
| t.start() |
| log.info("Bot lanzado en hilo secundario") |
|
|
| port = int(os.environ.get("PORT", 7860)) |
| log.info(f"Servidor FastAPI en puerto {port}") |
| uvicorn.run(api, host="0.0.0.0", port=port) |
|
|