| """ |
| app.py |
| Point d'entrée du Space Hugging Face (SDK Docker). |
| |
| Ce fichier fait deux choses en parallèle : |
| 1. Lance le bot Telegram (bot.py) dans un thread secondaire en polling. |
| 2. Démarre un serveur web Flask minimal sur le port attendu par HF Spaces |
| (variable d'env PORT, généralement 7860), qui sert uniquement à donner |
| à Hugging Face un "visiteur" actif quand on le ping depuis l'extérieur |
| (UptimeRobot, GitHub Actions, etc.), afin d'éviter la mise en veille |
| automatique après 48h d'inactivité du tier CPU Basic gratuit. |
| |
| Le serveur web ne sert à RIEN d'autre que ça : il n'expose aucune logique |
| métier du bot, juste un endpoint de healthcheck. |
| """ |
|
|
| import logging |
| import os |
| import threading |
| import traceback |
|
|
| from flask import Flask, jsonify |
|
|
| logging.basicConfig( |
| format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", |
| level=logging.INFO, |
| ) |
| logger = logging.getLogger("hilal_ai.app") |
|
|
| app = Flask(__name__) |
|
|
| |
| _bot_status = {"started": False, "error": None, "traceback": None} |
|
|
|
|
| @app.route("/") |
| def index(): |
| return jsonify( |
| { |
| "service": "Hilal Ai Telegram Bot", |
| "bot_started": _bot_status["started"], |
| "bot_error": _bot_status["error"], |
| "bot_traceback": _bot_status["traceback"], |
| } |
| ) |
|
|
|
|
| @app.route("/ping") |
| def ping(): |
| """Endpoint dédié au keep-alive externe (UptimeRobot, GitHub Actions...). |
| Doit répondre vite et toujours 200 si le process est vivant.""" |
| return jsonify({"status": "ok"}), 200 |
|
|
|
|
| @app.route("/debug-env") |
| def debug_env(): |
| """Endpoint de diagnostic temporaire : affiche les variables d'environnement |
| pertinentes telles que VRAIMENT reçues par le process Python, pour |
| distinguer un problème de configuration HF Spaces d'un bug de code. |
| Le token n'est jamais affiché en entier (seulement sa longueur et ses |
| premiers caractères), pour éviter de le divulguer si le Space est public. |
| À SUPPRIMER une fois le diagnostic terminé. |
| """ |
| token = os.environ.get("TELEGRAM_BOT_TOKEN", "") |
| base_url = os.environ.get("TELEGRAM_API_BASE_URL", "") |
| return jsonify( |
| { |
| "TELEGRAM_BOT_TOKEN_present": bool(token), |
| "TELEGRAM_BOT_TOKEN_length": len(token), |
| "TELEGRAM_BOT_TOKEN_prefix": token[:6] if token else None, |
| "TELEGRAM_API_BASE_URL_raw": repr(base_url), |
| "TELEGRAM_API_BASE_URL_present": bool(base_url), |
| } |
| ) |
|
|
|
|
| def _start_bot_thread(): |
| """Lance bot.run_bot_blocking() dans un thread daemon séparé du |
| serveur Flask. Toute exception est capturée pour ne pas tuer le |
| thread silencieusement sans laisser de trace dans les logs HF.""" |
| try: |
| import bot |
| _bot_status["started"] = True |
| bot.run_bot_blocking() |
| except Exception: |
| tb = traceback.format_exc() |
| logger.exception("Le bot Telegram a crashé dans son thread.") |
| _bot_status["started"] = False |
| _bot_status["error"] = "Voir bot_traceback pour le détail complet." |
| _bot_status["traceback"] = tb |
|
|
|
|
| def main(): |
| bot_thread = threading.Thread(target=_start_bot_thread, daemon=True, name="telegram-bot") |
| bot_thread.start() |
|
|
| port = int(os.environ.get("PORT", "7860")) |
| logger.info("Serveur web de ping démarré sur le port %d", port) |
| |
| |
| app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
| |