""" Конфигурация приложения - загрузка переменных окружения """ import os from pathlib import Path from dotenv import load_dotenv # Загрузить .env файл env_path = Path(__file__).parent.parent / '.env' load_dotenv(env_path) class Config: """Базовая конфигурация""" # ═══════════════════════════════════════════════════════════════ # TELEGRAM BOT # ═══════════════════════════════════════════════════════════════ TELEGRAM_BOT_TOKEN = os.getenv('TELEGRAM_BOT_TOKEN', '') TELEGRAM_TIMEOUT = int(os.getenv('TELEGRAM_TIMEOUT', '30')) if not TELEGRAM_BOT_TOKEN: raise ValueError( "❌ TELEGRAM_BOT_TOKEN не установлен в .env\n" "Получите токен у @BotFather в Telegram" ) # ═══════════════════════════════════════════════════════════════ # TELETHON (для групп, где боты не могут писать) # ═══════════════════════════════════════════════════════════════ USE_TELETHON = os.getenv('USE_TELETHON', 'false').lower() == 'true' TELETHON_API_ID = os.getenv('TELETHON_API_ID', '') TELETHON_API_HASH = os.getenv('TELETHON_API_HASH', '') TELETHON_PHONE = os.getenv('TELETHON_PHONE', '') TELETHON_FLOOD_WAIT_MAX = int(os.getenv('TELETHON_FLOOD_WAIT_MAX', '60')) # Максимум ждать при FloodWait if USE_TELETHON: if not TELETHON_API_ID or not TELETHON_API_HASH or not TELETHON_PHONE: raise ValueError( "❌ Для использования Telethon нужны:\n" " TELETHON_API_ID\n" " TELETHON_API_HASH\n" " TELETHON_PHONE\n" "Получите их на https://my.telegram.org" ) # ═══════════════════════════════════════════════════════════════ # DATABASE # ═══════════════════════════════════════════════════════════════ DATABASE_URL = os.getenv('DATABASE_URL', 'sqlite+aiosqlite:///./autoposter.db') # Альтернативная конфигурация PostgreSQL DB_USER = os.getenv('DB_USER') DB_PASSWORD = os.getenv('DB_PASSWORD') DB_HOST = os.getenv('DB_HOST', 'localhost') DB_PORT = os.getenv('DB_PORT', '5432') DB_NAME = os.getenv('DB_NAME') # Если указаны отдельные параметры, построить URL if DB_USER and DB_PASSWORD and DB_NAME: DATABASE_URL = ( f'postgresql+asyncpg://{DB_USER}:{DB_PASSWORD}' f'@{DB_HOST}:{DB_PORT}/{DB_NAME}' ) # ═══════════════════════════════════════════════════════════════ # LOGGING # ═══════════════════════════════════════════════════════════════ LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO') LOG_MAX_SIZE = int(os.getenv('LOG_MAX_SIZE', '10485760')) LOG_BACKUP_COUNT = int(os.getenv('LOG_BACKUP_COUNT', '5')) # ═══════════════════════════════════════════════════════════════ # BOT SETTINGS # ═══════════════════════════════════════════════════════════════ MAX_RETRIES = int(os.getenv('MAX_RETRIES', '3')) RETRY_DELAY = int(os.getenv('RETRY_DELAY', '5')) MIN_SEND_INTERVAL = float(os.getenv('MIN_SEND_INTERVAL', '0.5')) # Минимум между отправками # ═══════════════════════════════════════════════════════════════ # PARSING SETTINGS # ═══════════════════════════════════════════════════════════════ ENABLE_KEYWORD_PARSING = os.getenv('ENABLE_KEYWORD_PARSING', 'true').lower() == 'true' GROUP_PARSE_INTERVAL = int(os.getenv('GROUP_PARSE_INTERVAL', '3600')) MAX_MEMBERS_TO_LOAD = int(os.getenv('MAX_MEMBERS_TO_LOAD', '1000')) # ═══════════════════════════════════════════════════════════════ # OPTIONAL SETTINGS # ═══════════════════════════════════════════════════════════════ ENABLE_STATISTICS = os.getenv('ENABLE_STATISTICS', 'true').lower() == 'true' MESSAGE_HISTORY_DAYS = int(os.getenv('MESSAGE_HISTORY_DAYS', '30')) WEBHOOK_URL = os.getenv('WEBHOOK_URL') WEBHOOK_PORT = int(os.getenv('WEBHOOK_PORT', '8443')) if os.getenv('WEBHOOK_PORT') else None # ═══════════════════════════════════════════════════════════════ # CELERY & REDIS SETTINGS # ═══════════════════════════════════════════════════════════════ REDIS_HOST = os.getenv('REDIS_HOST', 'redis') REDIS_PORT = int(os.getenv('REDIS_PORT', '6379')) REDIS_DB = int(os.getenv('REDIS_DB', '0')) REDIS_PASSWORD = os.getenv('REDIS_PASSWORD', '') # Построить URL Redis if REDIS_PASSWORD: CELERY_BROKER_URL = f'redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}' CELERY_RESULT_BACKEND_URL = f'redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB + 1}' else: CELERY_BROKER_URL = f'redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}' CELERY_RESULT_BACKEND_URL = f'redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB + 1}' # ═══════════════════════════════════════════════════════════════ # MODES # ═══════════════════════════════════════════════════════════════ BOT_MODE = 'bot' # 'bot' для бота, 'client' для Telethon клиента USE_CLIENT_WHEN_BOT_FAILS = True # Использовать Telethon если бот не может отправить @classmethod def get_mode(cls) -> str: """Получить текущий режим работы""" if cls.USE_TELETHON: return 'hybrid' # Используем оба: бот и клиент return cls.BOT_MODE @classmethod def get_database_url(cls) -> str: """Получить URL БД""" return cls.DATABASE_URL @classmethod def validate(cls) -> bool: """Проверить конфигурацию""" # Основное - токен бота if not cls.TELEGRAM_BOT_TOKEN: return False # Если Telethon включен - проверить его конфиг if cls.USE_TELETHON: if not (cls.TELETHON_API_ID and cls.TELETHON_API_HASH and cls.TELETHON_PHONE): return False return True # Создать экземпляр конфигурации config = Config() # Выводы при импорте if config.get_mode() == 'hybrid': import logging logger = logging.getLogger(__name__) logger.info("🔀 Гибридный режим: бот + Telethon клиент") elif config.USE_TELETHON: import logging logger = logging.getLogger(__name__) logger.info("📱 Режим Telethon клиента") else: import logging logger = logging.getLogger(__name__) logger.info("🤖 Режим Telegram бота")