livegram / app /main.py
Akay Borana
force deploy new code
6f82d5b
Raw
History Blame Contribute Delete
4.76 kB
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
# Set up specific logger for this file
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:
# Set level to DEBUG and ensure it prints instantly to stdout
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 ===")
# 1. Start the dummy server FIRST to satisfy Hugging Face
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)...")
# If it hangs, it will be exactly here.
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())