""" Конфигурация бота """ import os from dotenv import load_dotenv from pathlib import Path # Загружаем переменные окружения (override=True для перезагрузки) load_dotenv(override=True) # Telegram BOT_TOKEN = os.getenv('BOT_TOKEN', '') ADMIN_CHAT_ID = int(os.getenv('ADMIN_CHAT_ID', '0')) ADMIN_USER_ID = int(os.getenv('ADMIN_USER_ID', '0')) # База данных BASE_DIR = Path(__file__).resolve().parent DATABASE_PATH = os.getenv('DATABASE_PATH', str(BASE_DIR / 'database' / 'domovoy.db')) DB_TYPE = os.getenv('DB_TYPE', 'sqlite').lower() DATABASE_URL = os.getenv('DATABASE_URL', f'sqlite+aiosqlite:///{DATABASE_PATH}') DATABASE_URL_SYNC = os.getenv('DATABASE_URL_SYNC', f'sqlite:///{DATABASE_PATH}') # Экспорт EXPORT_DIR = os.getenv('EXPORT_DIR', str(BASE_DIR / 'exports')) EXPORT_SCHEDULE = os.getenv('EXPORT_SCHEDULE', '0 3 * * 0') # Детект шпионов SPY_DETECTION_ENABLED = os.getenv('SPY_DETECTION_ENABLED', 'true').lower() == 'true' SPY_ALERT_USER_ID = int(os.getenv('SPY_ALERT_USER_ID', '0')) # Логирование LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO') LOG_FILE = os.getenv('LOG_FILE', str(BASE_DIR / 'logs' / 'bot.log')) # ===== ПРОКСИ ===== USE_PROXY = os.getenv('USE_PROXY', 'false').lower() == 'true' PROXY_TYPE = os.getenv('PROXY_TYPE', 'socks5').lower() PROXY_HOST = os.getenv('PROXY_HOST', '127.0.0.1') PROXY_PORT = int(os.getenv('PROXY_PORT', '10808')) # ===== ВЕБ-ИНТЕРФЕЙС ===== WEB_ADMIN_LOGIN = os.getenv('WEB_ADMIN_LOGIN', 'admin') WEB_ADMIN_PASSWORD = os.getenv('WEB_ADMIN_PASSWORD', 'admin') WEB_ADMIN_HOST = os.getenv('WEB_ADMIN_HOST', '0.0.0.0') WEB_ADMIN_PORT = int(os.getenv('WEB_ADMIN_PORT', '8000')) # ===== TELEGRAM FORUM TOPICS ===== FORUM_ENABLED = os.getenv('FORUM_ENABLED', 'false').lower() == 'true' TOPIC_GENERAL = int(os.getenv('TOPIC_GENERAL', '1')) TOPIC_ADS = int(os.getenv('TOPIC_ADS', '1')) TOPIC_LINKS = int(os.getenv('TOPIC_LINKS', '1')) TOPIC_MEMES = int(os.getenv('TOPIC_MEMES', '1')) TOPIC_AUTO = int(os.getenv('TOPIC_AUTO', '1')) TOPIC_LOSTFOUND = int(os.getenv('TOPIC_LOSTFOUND', '1')) TOPIC_MEETINGS = int(os.getenv('TOPIC_MEETINGS', '1')) TOPIC_KGM = int(os.getenv('TOPIC_KGM', '1')) TOPIC_UO = int(os.getenv('TOPIC_UO', '1')) TOPIC_PHONES = int(os.getenv('TOPIC_PHONES', '1')) # Словарь всех тем FORUM_TOPICS = { 'general': TOPIC_GENERAL, 'ads': TOPIC_ADS, 'links': TOPIC_LINKS, 'memes': TOPIC_MEMES, 'auto': TOPIC_AUTO, 'lostfound': TOPIC_LOSTFOUND, 'meetings': TOPIC_MEETINGS, 'kgm': TOPIC_KGM, 'uo': TOPIC_UO, 'phones': TOPIC_PHONES, } # Проверка критичных настроек if not BOT_TOKEN: raise ValueError('BOT_TOKEN не настроен! Проверьте .env файл') if not ADMIN_CHAT_ID: raise ValueError('ADMIN_CHAT_ID не настроен!') if not ADMIN_USER_ID: raise ValueError('ADMIN_USER_ID не настроен! Укажите ваш Telegram ID') # ===== БЕЗОПАСНОСТЬ ===== SAFETY_MODE = os.getenv('SAFETY_MODE', 'production').lower() # 'production' или 'safe' # ===== ДИНАМИЧЕСКИЕ ПУТИ (ПЕРЕНОСИМОСТЬ) ===== MUTT_DIR = os.getenv('MUTT_DIR', '/app/mutt' if os.path.exists('/app/mutt') else str(BASE_DIR.parent.parent / 'mutt')) GOOGLE_CREDS_FILE = os.getenv('GOOGLE_CREDS_FILE', '/app/config/google_creds.json' if os.path.exists('/app/config/google_creds.json') else str(BASE_DIR.parent.parent / 'domovoy_google_creds.json')) def get_proxy_url() -> str | None: """Получить URL прокси для aiohttp""" if not USE_PROXY: return None if PROXY_TYPE == 'http': return f'http://{PROXY_HOST}:{PROXY_PORT}' elif PROXY_TYPE == 'socks5': return f'socks5://{PROXY_HOST}:{PROXY_PORT}' elif PROXY_TYPE == 'socks4': return f'socks4://{PROXY_HOST}:{PROXY_PORT}' else: return f'socks5://{PROXY_HOST}:{PROXY_PORT}' # Вспомогательные функции def get_admin_ids(): """Список ID администраторов""" ids = [ADMIN_USER_ID] extra_ids = os.getenv('EXTRA_ADMIN_IDS', '') if extra_ids: ids.extend([int(x.strip()) for x in extra_ids.split(',')]) return ids def is_admin(user_id: int) -> bool: """Проверка, является ли пользователь админом""" return user_id in get_admin_ids() def get_topic_id(topic_type: str) -> int: """ Получить ID темы Forum по типу контента Args: topic_type: тип контента ('ads', 'lostfound', 'meetings', etc.) Returns: message_thread_id для отправки в тему """ if not FORUM_ENABLED: return None # Отправлять в общую тему (без message_thread_id) return FORUM_TOPICS.get(topic_type.lower(), TOPIC_GENERAL)