Files
tg_loader/shared/config.py
2025-12-04 00:12:56 +03:00

132 lines
4.7 KiB
Python

"""
Shared configuration for bot and web application
"""
from pydantic_settings import BaseSettings
from typing import Optional
import os
class Settings(BaseSettings):
"""Application settings"""
# Telegram Bot
BOT_TOKEN: str
TELEGRAM_API_ID: int
TELEGRAM_API_HASH: str
OWNER_ID: int
# Authorization
AUTHORIZED_USERS: str = ""
ADMIN_IDS: str = ""
BLOCKED_USERS: str = ""
PRIVATE_MODE: bool = False # If True, only users from AUTHORIZED_USERS or database can use the bot
# Database
DATABASE_URL: str = "sqlite+aiosqlite:///./data/bot.db"
# Redis (for sessions)
REDIS_HOST: str = "localhost"
REDIS_PORT: int = 6379
REDIS_DB: int = 0
USE_REDIS_SESSIONS: bool = False # Use Redis for sessions instead of in-memory
# Web
WEB_HOST: str = "0.0.0.0"
WEB_PORT: int = 5000
WEB_SECRET_KEY: str = ""
# Logging
LOG_LEVEL: str = "INFO"
LOG_FILE: str = "logs/bot.log"
# Media Download
COOKIES_FILE: Optional[str] = None # Path to cookies file (Netscape format) for Instagram and other sites
# Download Limits
MAX_FILE_SIZE: Optional[str] = None # Maximum file size in bytes (empty or None = no limit)
MAX_DURATION_MINUTES: Optional[str] = None # Maximum duration in minutes (empty or None = no limit)
MAX_CONCURRENT_TASKS: int = 5 # Maximum number of concurrent tasks per user
@property
def max_file_size_bytes(self) -> Optional[int]:
"""Get maximum file size in bytes"""
if not self.MAX_FILE_SIZE or self.MAX_FILE_SIZE.strip() == '' or self.MAX_FILE_SIZE.lower() == 'none':
return None
try:
return int(self.MAX_FILE_SIZE)
except (ValueError, TypeError):
return None
@property
def max_duration_minutes_int(self) -> Optional[int]:
"""Get maximum duration in minutes"""
if not self.MAX_DURATION_MINUTES or self.MAX_DURATION_MINUTES.strip() == '' or self.MAX_DURATION_MINUTES.lower() == 'none':
return None
try:
return int(self.MAX_DURATION_MINUTES)
except (ValueError, TypeError):
return None
class Config:
# Configuration file structure:
# - .env - for Docker (used via docker-compose env_file)
# - .env.local - for local development (used here if not in Docker)
# In Docker, environment variables are passed through environment in docker-compose
# env_file is only used for local development
# In Docker, env_file should not be loaded as variables are passed through environment
# Load .env.local only if not in Docker (determined by DOCKER_ENV environment variable)
# In Docker, environment variables have priority over env_file
# If DOCKER_ENV is set, do not load .env.local file
env_file = None if os.getenv("DOCKER_ENV") else ".env.local"
env_file_encoding = "utf-8"
case_sensitive = True
# Pydantic Settings automatically reads environment variables from system
# Priority: environment variables > env_file > default values
@property
def authorized_users_list(self) -> list[int]:
"""List of authorized users"""
if not self.AUTHORIZED_USERS:
return []
return [int(uid.strip()) for uid in self.AUTHORIZED_USERS.split(",") if uid.strip()]
@property
def admin_ids_list(self) -> list[int]:
"""List of administrators"""
if not self.ADMIN_IDS:
return []
return [int(uid.strip()) for uid in self.ADMIN_IDS.split(",") if uid.strip()]
@property
def blocked_users_list(self) -> list[int]:
"""List of blocked users"""
if not self.BLOCKED_USERS:
return []
return [int(uid.strip()) for uid in self.BLOCKED_USERS.split(",") if uid.strip()]
# Global settings instance
settings = Settings()
# Log the DATABASE_URL being used on load (for debugging)
import logging
_logger = logging.getLogger(__name__)
# Log only if DATABASE_URL is not default SQLite
if settings.DATABASE_URL and "sqlite" not in settings.DATABASE_URL.lower():
db_url_safe = settings.DATABASE_URL
if '@' in db_url_safe:
# Hide password in logs
parts = db_url_safe.split('@')
if len(parts) == 2:
auth_part = parts[0].split('://')
if len(auth_part) == 2:
scheme = auth_part[0]
user_pass = auth_part[1]
if ':' in user_pass:
user = user_pass.split(':')[0]
db_url_safe = f"{scheme}://{user}:***@{parts[1]}"
_logger.info(f"Using DATABASE_URL: {db_url_safe}")
else:
_logger.warning(f"⚠️ Using SQLite database: {settings.DATABASE_URL}. For Docker, use PostgreSQL!")