import streamlit as st from typing import Any, Dict, List, Optional import time def safe_get(data: Dict, key: str, default: Any = None) -> Any: """Safely get nested dictionary values""" try: for k in key.split('.'): data = data[k] return data except (KeyError, TypeError): return default def format_duration(ms: int) -> str: """Convert milliseconds to MM:SS format""" seconds = ms // 1000 minutes = seconds // 60 seconds = seconds % 60 return f"{minutes}:{seconds:02d}" def parse_spotify_url(url: str) -> tuple: """Parse Spotify URL to get type and ID""" if 'track' in url: parts = url.split('/track/') if len(parts) > 1: track_id = parts[1].split('?')[0] return 'track', track_id elif 'playlist' in url: parts = url.split('/playlist/') if len(parts) > 1: playlist_id = parts[1].split('?')[0] return 'playlist', playlist_id elif 'artist' in url: parts = url.split('/artist/') if len(parts) > 1: artist_id = parts[1].split('?')[0] return 'artist', artist_id elif 'album' in url: parts = url.split('/album/') if len(parts) > 1: album_id = parts[1].split('?')[0] return 'album', album_id return None, None def validate_api_keys() -> bool: """Check if required API keys are set""" provider = st.session_state.ai_provider if provider == "OpenAI" and st.session_state.openai_api_key: return True elif provider == "Anthropic" and st.session_state.anthropic_api_key: return True elif provider == "OpenRouter" and st.session_state.openrouter_api_key: return True return False def get_spotify_image_url(item: Dict, size: str = 'medium') -> str: """Get image URL from Spotify item""" images = safe_get(item, 'images', []) if not images: images = safe_get(item, 'album.images', []) if not images: return "" if size == 'large': return images[0]['url'] elif size == 'medium': return images[len(images)//2]['url'] if len(images) > 1 else images[0]['url'] else: return images[-1]['url'] def create_track_uri(track_id: str) -> str: """Create Spotify track URI from ID""" return f"spotify:track:{track_id}" def create_playlist_uri(playlist_id: str) -> str: """Create Spotify playlist URI from ID""" return f"spotify:playlist:{playlist_id}" def chunk_list(lst: List, chunk_size: int) -> List[List]: """Split list into chunks""" return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)] def retry_with_backoff(func, max_retries=3, initial_delay=1): """Retry function with exponential backoff""" for i in range(max_retries): try: return func() except Exception as e: if i == max_retries - 1: raise e delay = initial_delay * (2 ** i) time.sleep(delay) return None