| import asyncio |
| import base64 |
| import logging |
| import sys |
| from pathlib import Path |
| from aiohttp import web |
|
|
| from app.bots.master import MasterController |
| from app.config import Settings |
| from app.session_manager import SessionManager |
| from app.storage.hf_dataset import HFDataStore |
|
|
| |
| logger = logging.getLogger("MAIN") |
|
|
| async def health_check(request): |
| return web.Response(text="Bot is running and healthy!") |
|
|
| async def start_dummy_server(): |
| try: |
| logger.info("Starting dummy web server on port 7860...") |
| app = web.Application() |
| app.router.add_get('/', health_check) |
| runner = web.AppRunner(app) |
| await runner.setup() |
| site = web.TCPSite(runner, '0.0.0.0', 7860) |
| await site.start() |
| logger.info("Dummy web server started SUCCESSFULLY.") |
| except Exception as e: |
| logger.error(f"Failed to start dummy server: {e}", exc_info=True) |
| raise |
|
|
| async def ensure_master_session(settings: Settings, store: HFDataStore) -> None: |
| logger.info("Checking master session state...") |
| session_file = Path(settings.master_session_file) |
| master = store.get_data().setdefault("master", {}) |
|
|
| if session_file.exists(): |
| logger.info(f"Local session file found at {session_file}. Backing up to store...") |
| master["session_b64"] = base64.b64encode(session_file.read_bytes()).decode("utf-8") |
| store.mark_dirty() |
| return |
|
|
| logger.info("No local session file found. Attempting to restore from HF store...") |
| raw_b64 = master.get("session_b64") |
| if raw_b64: |
| logger.info("Base64 session found in store. Decoding and saving to file...") |
| session_file.write_bytes(base64.b64decode(raw_b64.encode("utf-8"))) |
| logger.info("Session restored successfully.") |
| else: |
| logger.warning("WARNING: No session found in store or locally. A NEW session will be created. (If this is a userbot, it might hang here waiting for a login code!)") |
|
|
| async def main() -> None: |
| |
| logging.basicConfig( |
| level=logging.DEBUG, |
| format="%(asctime)s [%(levelname)s] %(name)s - %(message)s", |
| handlers=[logging.StreamHandler(sys.stdout)] |
| ) |
| logger.info("=== Application Startup Sequence Initiated ===") |
|
|
| |
| await start_dummy_server() |
|
|
| try: |
| logger.info("Step 1: Loading environment variables...") |
| settings = Settings.from_env() |
| if not settings.api_id or not settings.api_hash: |
| logger.error("CRITICAL: Missing API_ID or API_HASH") |
| raise RuntimeError("API_ID and API_HASH are required") |
| if not settings.hf_token or not settings.hf_repo_id: |
| logger.error("CRITICAL: Missing HF_TOKEN or HF_REPO_ID") |
| raise RuntimeError("HF_TOKEN and HF_REPO_ID are required") |
| logger.info("Environment variables loaded successfully.") |
|
|
| logger.info("Step 2: Initializing HFDataStore...") |
| store = HFDataStore(settings) |
| await store.initialize() |
| logger.info("HFDataStore initialized.") |
|
|
| logger.info("Step 3: Ensuring master session...") |
| await ensure_master_session(settings, store) |
|
|
| logger.info("Step 4: Initializing SessionManager and loading all sessions...") |
| sessions = SessionManager(settings, store) |
| await sessions.load_all() |
| logger.info("All sessions loaded.") |
|
|
| logger.info("Step 5: Initializing MasterController...") |
| master = MasterController(settings, store, sessions) |
| |
| logger.info("Step 6: Starting MasterController (Connecting to Telegram)...") |
| |
| await master.start() |
| logger.info("MasterController connected to Telegram successfully.") |
| |
| logger.info("Step 7: Starting HFDataStore auto-sync...") |
| await store.start_auto_sync() |
| logger.info("Auto-sync started.") |
|
|
| logger.info("=== SUCCESS: Entering main bot loop. Application is now fully RUNNING. ===") |
| await master.run() |
| |
| except BaseException as e: |
| logger.critical(f"FATAL ERROR during startup or execution: {e}", exc_info=True) |
| finally: |
| logger.info("=== Application Shutting Down ===") |
| try: |
| await store.sync(force=True) |
| await store.stop_auto_sync() |
| await sessions.shutdown() |
| await master.stop() |
| logger.info("Cleanup completed successfully.") |
| except Exception as cleanup_error: |
| logger.error(f"Error during cleanup: {cleanup_error}", exc_info=True) |
|
|
| if __name__ == "__main__": |
| asyncio.run(main()) |
| |
|
|