Spaces:
Running
Running
| """ | |
| Configuration management for Hugging Face Spaces deployment | |
| Handles environment variables and application settings | |
| """ | |
| import os | |
| from typing import Dict, Any | |
| from dotenv import load_dotenv | |
| # Load environment variables from .env file if it exists (for local development) | |
| load_dotenv() | |
| class Config: | |
| """Application configuration management""" | |
| def __init__(self): | |
| # No automatic environment variable loading - tokens come from Gradio interface only | |
| self.wildberries_api_token = None | |
| # Official Wildberries API URLs based on documentation | |
| self.wildberries_base_url = "https://statistics-api.wildberries.ru" | |
| self.wildberries_content_url = "https://content-api.wildberries.ru" | |
| self.wildberries_analytics_url = "https://seller-analytics-api.wildberries.ru" | |
| self.wildberries_common_url = "https://common-api.wildberries.ru" | |
| self.wildberries_marketplace_url = "https://marketplace-api.wildberries.ru" | |
| self.wildberries_supplies_url = "https://supplies-api.wildberries.ru" | |
| # Rate limiting settings (based on official documentation) | |
| # Statistics API: Maximum of 300 requests per minute | |
| self.rate_limit_requests = 300 # requests per minute | |
| self.rate_limit_window = 60 # seconds | |
| # Request timeout settings | |
| self.request_timeout = 30 # seconds | |
| self.max_retries = 3 | |
| self.retry_backoff_factor = 2 | |
| # Application settings | |
| self.demo_mode = True # Always start in demo mode, users provide tokens via UI | |
| self.debug_mode = os.getenv("DEBUG", "false").lower() == "true" | |
| # Hugging Face Spaces specific settings | |
| self.hf_space_id = os.getenv("SPACE_ID") | |
| self.hf_space_author = os.getenv("SPACE_AUTHOR_NAME") | |
| # Gradio settings | |
| self.gradio_analytics = os.getenv("GRADIO_ANALYTICS_ENABLED", "false").lower() == "true" | |
| self.gradio_theme = os.getenv("GRADIO_THEME", "soft") | |
| def get_api_headers(self, api_token: str = None) -> Dict[str, str]: | |
| """Get headers for Wildberries API requests""" | |
| headers = { | |
| "Content-Type": "application/json", | |
| "User-Agent": "Wildberries-Analytics-Dashboard/1.0" | |
| } | |
| if api_token: | |
| headers["Authorization"] = f"Bearer {api_token}" | |
| return headers | |
| def get_rate_limit_config(self) -> Dict[str, Any]: | |
| """Get rate limiting configuration""" | |
| return { | |
| "requests_per_minute": self.rate_limit_requests, | |
| "window_seconds": self.rate_limit_window, | |
| "backoff_factor": self.retry_backoff_factor | |
| } | |
| def is_configured(self, api_token: str = None) -> bool: | |
| """Check if the application is properly configured with API token""" | |
| return api_token is not None and len(api_token.strip()) > 0 | |
| def get_endpoints(self) -> Dict[str, str]: | |
| """Get API endpoint configurations based on working API calls""" | |
| return { | |
| # Statistics API endpoints - Correct sales endpoint | |
| "sales": f"{self.wildberries_base_url}/api/v1/supplier/sales", | |
| "orders": f"{self.wildberries_base_url}/api/v5/supplier/reportDetailByPeriod", | |
| "stocks": f"{self.wildberries_base_url}/api/v1/supplier/stocks", | |
| "incomes": f"{self.wildberries_base_url}/api/v5/supplier/reportDetailByPeriod", | |
| "reportDetailByPeriod": f"{self.wildberries_base_url}/api/v5/supplier/reportDetailByPeriod", | |
| # Analytics API endpoints | |
| "analytics": f"{self.wildberries_analytics_url}/api/v2/nm-report/detail", | |
| # Content API endpoints | |
| "content": f"{self.wildberries_content_url}/content/v1/cards/cursor/list", | |
| # Common API endpoints | |
| "news": f"{self.wildberries_common_url}/api/communications/v2/news", | |
| "seller_info": f"{self.wildberries_common_url}/api/v1/seller-info", | |
| # Connection check endpoints for each service | |
| "ping_statistics": f"{self.wildberries_base_url}/ping", | |
| "ping_content": f"{self.wildberries_content_url}/ping", | |
| "ping_analytics": f"{self.wildberries_analytics_url}/ping", | |
| "ping_common": f"{self.wildberries_common_url}/ping", | |
| "ping_marketplace": f"{self.wildberries_marketplace_url}/ping", | |
| "ping_supplies": f"{self.wildberries_supplies_url}/ping" | |
| } | |
| def validate_token(self, token: str) -> bool: | |
| """Validate the format of a Wildberries API token (JWT format)""" | |
| if not token: | |
| return False | |
| # Wildberries tokens are JWT format based on official documentation | |
| try: | |
| # Check if it looks like a JWT (three parts separated by dots) | |
| parts = token.split('.') | |
| if len(parts) != 3: | |
| return False | |
| # Check minimum length (JWT tokens are typically longer) | |
| if len(token) < 50: | |
| return False | |
| return True | |
| except Exception: | |
| return False | |
| def get_demo_settings(self) -> Dict[str, Any]: | |
| """Get settings for demo mode""" | |
| return { | |
| "demo_products_count": 15, | |
| "demo_sales_days": 30, | |
| "demo_revenue_range": (10000, 500000), # rubles | |
| "demo_stock_range": (0, 1000), | |
| "demo_categories": [ | |
| "Одежда", "Обувь", "Аксессуары", "Красота", | |
| "Дом и сад", "Спорт", "Электроника", "Книги" | |
| ] | |
| } | |
| def __repr__(self) -> str: | |
| """String representation of configuration""" | |
| return f""" | |
| Wildberries Analytics Dashboard Configuration: | |
| - Demo Mode: {self.demo_mode} | |
| - Debug Mode: {self.debug_mode} | |
| - API Configured: {self.is_configured()} | |
| - Rate Limit: {self.rate_limit_requests}/min | |
| - HF Space: {self.hf_space_author}/{self.hf_space_id if self.hf_space_id else 'local'} | |
| """ | |
| # Global configuration instance | |
| _config = None | |
| def get_config() -> Config: | |
| """Get the global configuration instance""" | |
| global _config | |
| if _config is None: | |
| _config = Config() | |
| return _config | |
| def reload_config() -> Config: | |
| """Reload configuration (useful for testing)""" | |
| global _config | |
| _config = Config() | |
| return _config | |
| # Environment validation for Hugging Face Spaces | |
| def validate_hf_environment(): | |
| """Validate that we're running in a proper HF Spaces environment""" | |
| config = get_config() | |
| issues = [] | |
| if not config.wildberries_api_token: | |
| issues.append("WILDBERRIES_API_TOKEN not set - running in demo mode") | |
| if config.wildberries_api_token and not config.validate_token(config.wildberries_api_token): | |
| issues.append("WILDBERRIES_API_TOKEN appears to be invalid format") | |
| return issues | |
| # Export commonly used configurations | |
| DEFAULT_CONFIG = get_config() | |
| API_ENDPOINTS = DEFAULT_CONFIG.get_endpoints() | |
| RATE_LIMIT_CONFIG = DEFAULT_CONFIG.get_rate_limit_config() | |
| DEMO_SETTINGS = DEFAULT_CONFIG.get_demo_settings() |