Spaces:
Runtime error
Runtime error
# main.py | |
import os | |
import logging | |
import asyncio | |
from concurrent.futures import ThreadPoolExecutor | |
from hydrogram import Client, idle | |
from hydrogram.errors import AuthKeyUnregistered | |
from config import Config | |
import handlers # To access register_handlers | |
# --- Global Executor --- | |
# Defined here so it can be imported by handlers if structured that way, | |
# or simply passed/used within main_async_logic. | |
# max_workers can be adjusted based on CPU cores or expected load. | |
executor = ThreadPoolExecutor(max_workers=(os.cpu_count() or 1) + 4) | |
# --- Logging Setup --- | |
def setup_logging(): | |
logging.basicConfig( | |
level=logging.INFO, | |
format='%(asctime)s - %(name)s - %(levelname)s - [%(module)s.%(funcName)s:%(lineno)d] - %(message)s', | |
) | |
logging.getLogger("hydrogram").setLevel(logging.WARNING) # Reduce hydrogram verbosity | |
return logging.getLogger(__name__) | |
logger = setup_logging() | |
# --- Directory and Font Checks --- | |
def run_startup_checks(): | |
logger.info("Running startup checks...") | |
# Check directories (expected to be created by Dockerfile or COPY . .) | |
if not os.path.isdir(Config.PREDEFINED_TEMPLATES_DIR): | |
logger.error(f"FATAL: Templates directory '{Config.PREDEFINED_TEMPLATES_DIR}' not found or is not a directory in the repository root.") | |
return False | |
if not os.path.isdir(Config.OUTPUT_DIR): # This one is created by Dockerfile if not present | |
logger.info(f"Output directory '{Config.OUTPUT_DIR}' not found, will be created by Dockerfile.") | |
# It's okay if this one is missing initially, Dockerfile handles it. | |
# But templates dir *must* come from repo. | |
# Check if templates directory has content (optional but good) | |
try: | |
if os.path.isdir(Config.PREDEFINED_TEMPLATES_DIR) and not os.listdir(Config.PREDEFINED_TEMPLATES_DIR): | |
logger.warning(f"Templates directory '{Config.PREDEFINED_TEMPLATES_DIR}' is empty. Predefined templates will not work.") | |
except Exception as e: | |
logger.warning(f"Could not check contents of templates directory: {e}") | |
logger.info("Required directories check complete.") | |
logger.info(f"Attempting to use font: '{Config.FONT_PATH}' (requires system font access).") | |
return True | |
# --- Main Application Logic --- | |
async def main_async_logic(): | |
logger.info("Initializing Hydrogram Bot Client...") | |
app = Client( | |
name=Config.SESSION_NAME, | |
api_id=Config.API_ID, | |
api_hash=Config.API_HASH, | |
bot_token=Config.BOT_TOKEN, | |
workdir="/app" # Ensures .session file is stored in /app (writable) | |
) | |
handlers.register_handlers(app) | |
logger.info("Message handlers registered.") | |
try: | |
logger.info("Starting Hydrogram client (as BOT)...") | |
await app.start() | |
me = await app.get_me() | |
logger.info(f"Successfully started. Bot: {me.first_name} (Username: @{me.username}, ID: {me.id})") | |
logger.info("Bot is up and listening for messages from admins!") | |
await idle() | |
except AuthKeyUnregistered: | |
logger.critical("BOT TOKEN INVALID or REVOKED. Please check your BOT_TOKEN secret in Hugging Face.") | |
except Exception as e: | |
logger.critical(f"Error starting or running Hydrogram client: {e}", exc_info=True) | |
finally: | |
logger.info("Shutting down executor...") | |
executor.shutdown(wait=True) | |
if app.is_initialized and app.is_connected: # Check if client was started | |
logger.info("Stopping Hydrogram client...") | |
await app.stop() | |
logger.info("Shutdown complete.") | |
if __name__ == "__main__": | |
if not run_startup_checks(): | |
logger.critical("Startup checks failed. Exiting.") | |
exit(1) | |
try: | |
asyncio.run(main_async_logic()) | |
except KeyboardInterrupt: | |
logger.info("Bot stopped by KeyboardInterrupt.") | |
except Exception as e: | |
logger.critical(f"Unhandled exception in main: {e}", exc_info=True) | |
finally: | |
logger.info("Application terminated.") | |