tele_bot / app.py
PRC142004's picture
Upload 23 files
34c461b verified
"""
Climate-Resilient Agriculture Platform - Unified Entry Point
Optimized for Hugging Face Spaces and single-container deployment
Starts ALL services:
1. Pest Prediction API (Port 8000)
2. Weather Intelligence API (Port 8001)
3. Water Management API (Port 8002)
4. Master API Server (Port 7860/8003)
5. Telegram Bot (Background Task)
"""
import os
import sys
import asyncio
import logging
import threading
import time
from pathlib import Path
from dotenv import load_dotenv
import uvicorn
# Load environment variables
load_dotenv()
# Setup logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger("MasterApp")
# Ensure required directories exist
Path("data").mkdir(exist_ok=True)
# Define services to run
# Format: (module_name, port_number)
SERVICES = [
("pest:app", 8000),
("weather:app", 8001),
("water:app", 8002)
]
def run_service(app_path: str, port: int):
"""Run a sub-service in its own thread"""
try:
logger.info(f"[STARTUP] Launching {app_path} on port {port}...")
uvicorn.run(
app_path,
host="127.0.0.1",
port=port,
log_level="error", # Keep logs clean
access_log=False
)
except Exception as e:
logger.error(f"[ERROR] Service {app_path} failed: {e}")
def run_telegram_bot():
"""Runs Telegram bot in its own event loop"""
try:
logger.info("[BOT] Initializing Telegram bot thread...")
# Give services time to start up
time.sleep(5)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
from telegram_bot import main as bot_main
# If bot_main is async → await it
if asyncio.iscoroutinefunction(bot_main):
loop.run_until_complete(bot_main())
else:
bot_main()
except Exception as e:
logger.warning(f"[BOT WARNING] Telegram bot failed to initialize: {type(e).__name__}")
logger.info(f"[BOT INFO] This is normal if there's no internet/network access")
logger.info(f"[BOT INFO] REST APIs will continue working without the bot")
# Don't crash the app - just continue without the bot
def run_app():
"""Starts the full platform"""
logger.info("=" * 80)
logger.info("🌾 FarmSense MASTER STARTUP")
logger.info("=" * 80)
# 1. Start sub-services in background threads
for app_path, port in SERVICES:
t = threading.Thread(target=run_service, args=(app_path, port), daemon=True)
t.start()
logger.info(f"[STARTUP] {app_path} started in background")
# 2. Wait a moment for services to bind
time.sleep(2)
# 3. Start Telegram bot in background thread
bot_thread = threading.Thread(
target=run_telegram_bot,
name="TelegramBotThread",
daemon=True
)
bot_thread.start()
logger.info("[STARTUP] Telegram Bot started in background")
# 4. Run Main Master API on port 7860 (Hugging Face Default)
# This remains on the main thread
main_port = int(os.getenv("PORT", 7860))
logger.info(f"[STARTUP] Master API starting on port {main_port}...")
uvicorn.run(
"api_server:app",
host="0.0.0.0",
port=main_port,
log_level="info",
access_log=True,
reload=False
)
if __name__ == "__main__":
try:
run_app()
except KeyboardInterrupt:
logger.info("[SHUTDOWN] Graceful shutdown initiated")
except Exception as e:
logger.exception(f"[FATAL ERROR] {e}")
sys.exit(1)
finally:
logger.info("[EXIT] Application stopped")