File size: 3,057 Bytes
aac535a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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