Merge remote changes with local config improvements
- Merged remote .env.example updates - Kept local graceful config error handling - Kept local SMTP username/password variables
This commit is contained in:
59
.env.example
59
.env.example
@@ -0,0 +1,59 @@
|
|||||||
|
# Price Tracker Environment Variables
|
||||||
|
# Copy this file to .env and uncomment/modify the variables you want to override
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# Database Configuration
|
||||||
|
# ================================
|
||||||
|
# Path to the SQLite database file
|
||||||
|
DATABASE_PATH=/app/data/price_tracker.db
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# Scraping Configuration
|
||||||
|
# ================================
|
||||||
|
# Delay between requests in seconds (default: 2)
|
||||||
|
DELAY_BETWEEN_REQUESTS=2
|
||||||
|
|
||||||
|
# Maximum concurrent requests (default: 1)
|
||||||
|
MAX_CONCURRENT_REQUESTS=1
|
||||||
|
|
||||||
|
# Request timeout in seconds (default: 30)
|
||||||
|
REQUEST_TIMEOUT=30
|
||||||
|
|
||||||
|
# Number of retry attempts (default: 3)
|
||||||
|
RETRY_ATTEMPTS=3
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# Email Notifications
|
||||||
|
# ================================
|
||||||
|
# Enable/disable email notifications (true/false)
|
||||||
|
EMAIL_ENABLED=false
|
||||||
|
|
||||||
|
# SMTP server settings
|
||||||
|
SMTP_SERVER=smtp.gmail.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
|
||||||
|
# Email credentials (use app passwords for Gmail)
|
||||||
|
SENDER_EMAIL=your-email@gmail.com
|
||||||
|
SENDER_PASSWORD=your-app-password
|
||||||
|
|
||||||
|
# Where to send price alerts
|
||||||
|
RECIPIENT_EMAIL=alerts@yourdomain.com
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# Webhook Notifications
|
||||||
|
# ================================
|
||||||
|
# Enable/disable webhook notifications (true/false)
|
||||||
|
WEBHOOK_ENABLED=false
|
||||||
|
|
||||||
|
# Webhook URL for price alerts
|
||||||
|
WEBHOOK_URL=https://your-webhook-url.com/notify
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# Flask Application
|
||||||
|
# ================================
|
||||||
|
# Flask environment (development/production)
|
||||||
|
FLASK_ENV=production
|
||||||
|
|
||||||
|
# Python settings
|
||||||
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|||||||
@@ -273,6 +273,87 @@ class Config:
|
|||||||
# Return as string
|
# Return as string
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def _apply_env_overrides(self):
|
||||||
|
"""Apply environment variable overrides to configuration."""
|
||||||
|
# Database path override
|
||||||
|
if os.getenv('DATABASE_PATH'):
|
||||||
|
if 'database' not in self._config:
|
||||||
|
self._config['database'] = {}
|
||||||
|
self._config['database']['path'] = os.getenv('DATABASE_PATH')
|
||||||
|
|
||||||
|
# Email notification overrides
|
||||||
|
email_env_vars = {
|
||||||
|
'SMTP_SERVER': ['notifications', 'email', 'smtp_server'],
|
||||||
|
'SMTP_PORT': ['notifications', 'email', 'smtp_port'],
|
||||||
|
'SENDER_EMAIL': ['notifications', 'email', 'sender_email'],
|
||||||
|
'SENDER_PASSWORD': ['notifications', 'email', 'sender_password'],
|
||||||
|
'RECIPIENT_EMAIL': ['notifications', 'email', 'recipient_email'],
|
||||||
|
'EMAIL_ENABLED': ['notifications', 'email', 'enabled']
|
||||||
|
}
|
||||||
|
|
||||||
|
for env_var, config_path in email_env_vars.items():
|
||||||
|
env_value = os.getenv(env_var)
|
||||||
|
if env_value is not None:
|
||||||
|
self._set_nested_config(config_path, env_value)
|
||||||
|
|
||||||
|
# Webhook notification overrides
|
||||||
|
webhook_env_vars = {
|
||||||
|
'WEBHOOK_URL': ['notifications', 'webhook', 'url'],
|
||||||
|
'WEBHOOK_ENABLED': ['notifications', 'webhook', 'enabled']
|
||||||
|
}
|
||||||
|
|
||||||
|
for env_var, config_path in webhook_env_vars.items():
|
||||||
|
env_value = os.getenv(env_var)
|
||||||
|
if env_value is not None:
|
||||||
|
self._set_nested_config(config_path, env_value)
|
||||||
|
|
||||||
|
# Scraping configuration overrides
|
||||||
|
scraping_env_vars = {
|
||||||
|
'DELAY_BETWEEN_REQUESTS': ['scraping', 'delay_between_requests'],
|
||||||
|
'MAX_CONCURRENT_REQUESTS': ['scraping', 'max_concurrent_requests'],
|
||||||
|
'REQUEST_TIMEOUT': ['scraping', 'timeout'],
|
||||||
|
'RETRY_ATTEMPTS': ['scraping', 'retry_attempts']
|
||||||
|
}
|
||||||
|
|
||||||
|
for env_var, config_path in scraping_env_vars.items():
|
||||||
|
env_value = os.getenv(env_var)
|
||||||
|
if env_value is not None:
|
||||||
|
self._set_nested_config(config_path, env_value)
|
||||||
|
|
||||||
|
def _set_nested_config(self, path: list, value: str):
|
||||||
|
"""Set a nested configuration value from environment variable."""
|
||||||
|
# Convert string values to appropriate types
|
||||||
|
converted_value = self._convert_env_value(value)
|
||||||
|
|
||||||
|
# Navigate to the correct nested location
|
||||||
|
current = self._config
|
||||||
|
for key in path[:-1]:
|
||||||
|
if key not in current:
|
||||||
|
current[key] = {}
|
||||||
|
current = current[key]
|
||||||
|
|
||||||
|
current[path[-1]] = converted_value
|
||||||
|
|
||||||
|
def _convert_env_value(self, value: str):
|
||||||
|
"""Convert environment variable string to appropriate type."""
|
||||||
|
# Handle boolean values
|
||||||
|
if value.lower() in ('true', 'false'):
|
||||||
|
return value.lower() == 'true'
|
||||||
|
|
||||||
|
# Handle integer values
|
||||||
|
if value.isdigit():
|
||||||
|
return int(value)
|
||||||
|
|
||||||
|
# Handle float values
|
||||||
|
try:
|
||||||
|
if '.' in value:
|
||||||
|
return float(value)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Return as string
|
||||||
|
return value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def database_path(self) -> str:
|
def database_path(self) -> str:
|
||||||
"""Get database file path."""
|
"""Get database file path."""
|
||||||
|
|||||||
Reference in New Issue
Block a user