Add source
This commit is contained in:
131
shared/config.py
Normal file
131
shared/config.py
Normal file
@@ -0,0 +1,131 @@
|
||||
"""
|
||||
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!")
|
||||
|
||||
Reference in New Issue
Block a user