o
    ikC                     @   s   d Z ddlZddlmZ edZdadadd Zdd Zd	d
 Z	d&ddZ
d'ddZd'ddZdd Zdd Zdd Zdd Zdd Zdd Zd(d d!Zd&d"d#Zd$d% ZdS ))u  
Spotify Module for Luke.

Gives Luke control over Bill's Spotify — now playing, recent tracks,
top artists, playback control, and playlist management.

WhatsApp commands:
  "what's playing" / "now playing" → current track
  "recent" / "recently played" → last 5 tracks
  "play [song/artist]" → search and play
  "pause" / "stop" → pause playback
  "skip" / "next" → skip to next track
  "queue [song]" → add to queue
  "top artists" / "top tracks" → listening stats
  "playlist [name]" → play a playlist by name
    N)datetimespotifyc               
   C   s   t du rAzddlm}  |  atdua t rtd W tS td W tS  ty@ } ztd|  da W Y d}~tS d}~ww tS )z%Get the Spotify client (lazy-loaded).Nr   )get_spotify_clientzSpotify module: ACTIVEz4Spotify module: INACTIVE (run setup_spotify_auth.py)zSpotify init failed: F)
_availablespotify_authr   _clientloggerinfo	Exceptionerror)r   e r   I/sessions/lucid-sleepy-lamport/mnt/clawd/whatsapp-agent/spotify_module.py_get_client   s"   r   c                   C   s
   t   tS )zCheck if Spotify is connected.)r   r   r   r   r   r   is_available.   s   r   c               
   C   sp  t  } | sdS z|  }|r|dsW dS |di }|dd}ddd	 |d
g D }|di dd}|dd}|dd}|d  d|d d d}|d  d|d d d}	|di dd}
d| d| g}|r|d|  || d|	 d|
  d|W S  ty } ztd|  dt|dd  d W  Y d}~S d}~ww )!z Get the currently playing track.9   Spotify not connected. Run setup_spotify_auth.py — Luke
is_playingu#   Nothing playing right now. — LukeitemnameUnknown, c                 s       | ]}|d  V  qdS r   Nr   .0ar   r   r   	<genexpr>A       znow_playing.<locals>.<genexpr>artistsalbum progress_msr   duration_msi`  :i  02ddevicezUnknown deviceu   NOW PLAYING — Lukezby zAlbum: z / z on 
zNow playing error: zCouldn't get playback info: NP   	    — Luke)	r   current_playbackgetjoinappendr
   r   r   str)spcurrentr   trackr   r   r!   r"   progressdurationr%   linesr   r   r   r   now_playing4   s:   $r4      c              
   C   s>  t  }|sdS zq|j| d}|dg }|sW dS ddg}|D ]S}|d }|dd	}d
dd |dg D }|dd}	zt|	dd}
|
d}W n tt	fy\   d}Y nw |
d| d|  |rr|
d|  qd|W S  ty } ztd|  dt|dd  dW  Y d}~S d}~ww )zGet recently played tracks.r   limititemsu%   No recent listening history. — Lukeu   RECENTLY PLAYED — Luker    r0   r   r   r   c                 s   r   r   r   r   r   r   r   r   l   r   z"recently_played.<locals>.<genexpr>r   	played_atZz+00:00z	%-I:%M %p      —     r&   zRecently played error: zCouldn't fetch recent tracks: Nr'   r(   )r   current_user_recently_playedr*   r+   r   fromisoformatreplacestrftime
ValueErrorAttributeErrorr,   r
   r   r   r-   )r7   r.   recentr8   r3   r   r0   r   r   r9   dttime_strr   r   r   r   recently_played[   s<   $rG   medium_termc              
   C   s  t  }|sdS z\|j|| d}|dg }|sW dS dddd| | }d	| d
dg}t|dD ],\}}|dd}	d|dg dd }
|d| d|	  |
r]|d|
  q1d|W S  ty } ztd|  dt	|dd  dW  Y d}~S d}~ww )zt
    Get Bill's top artists.
    time_range: short_term (4 weeks), medium_term (6 months), long_term (all time)
    r   r7   
time_ranger8   '   Not enough listening data yet. — LukeLast 4 WeeksLast 6 MonthsAll Time
short_termrH   	long_termzTOP ARTISTS (
   ) — Luker       r   r   r   genresN   r;   .      r&   zTop artists error: zCouldn't fetch top artists: r'   r(   )
r   current_user_top_artistsr*   	enumerater+   r,   r
   r   r   r-   )rJ   r7   r.   resultr8   range_labelr3   iartistr   rT   r   r   r   r   top_artists   s8   $r^   c              
   C   s  t  }|sdS zV|j|| d}|dg }|sW dS dddd| | }d	| d
dg}t|dD ]&\}}|dd}	ddd |dg D }
|d| d|	 d|
  q1d|W S  ty } ztd|  dt	|dd  dW  Y d}~S d}~ww )zGet Bill's top tracks.r   rI   r8   rK   rL   rM   rN   rO   zTOP TRACKS (rR   r    rS   r   r   r   c                 s   r   r   r   r   r   r   r   r      r   ztop_tracks.<locals>.<genexpr>r   r;   rV   r<   r&   zTop tracks error: zCouldn't fetch top tracks: Nr'   r(   )
r   current_user_top_tracksr*   rY   r+   r,   r
   r   r   r-   )rJ   r7   r.   rZ   r8   r[   r3   r\   r0   r   r   r   r   r   r   
top_tracks   s2   $r`   c              
   C   s  t  }|sdS z| }dd |dg D }|dg }|s$|s$W dS |r,|d d n|d d }|j| dd	d
}|di dg }|di dg }|di dg }	|D ]'}
|  |
d  v r|j||
d d d|
d  d|
d d  d  W S qZ|r|d }|d }ddd |dg D }|j||d gd d| d| dW S |	r|	d }|j||d d d|d  dW S d|  dW S  ty } z-t|}d |v sd!|v rW Y d"}~d#S t	
d$|  d%t|d"d&  dW  Y d"}~S d"}~ww )'z7Search for a song/artist/playlist and start playing it.r   c                 S   s   g | ]	}| d r|qS )	is_active)r*   )r   dr   r   r   
<listcomp>   s    zplay_search.<locals>.<listcomp>devicesuP   No Spotify devices found. Open Spotify on your phone or computer first. — Luker   idzplaylist,track,artist   qtyper7   	playlistsr8   tracksr   r   uri)	device_idcontext_urizPlaying playlist:  (total    tracks) — Luker   c                 s   r   r   r   r   r   r   r   r      r   zplay_search.<locals>.<genexpr>)rm   uris	Playing:  by r(   u    (artist radio) — LukezCouldn't find anything for 'u$   '. Try being more specific. — LukeNO_ACTIVE_DEVICE404Nu@   No active Spotify device. Open Spotify somewhere first. — LukezPlay search error: zPlayback error: r'   )r   rd   r*   searchlowerstart_playbackr+   r
   r-   r   r   )queryr.   rd   active
any_devicerm   resultsrj   rk   r   plr0   r   artist_namer]   r   	error_msgr   r   r   play_search   sL   $$r   c               
   C   t   t  } | sdS z|   W dS  ty9 } zdt|v r#W Y d}~dS dt|dd  dW  Y d}~S d}~ww )	zPause playback.   Spotify not connected. — Lukeu   Paused. — Lukeru   Nu   Nothing is playing. — LukezPause error: r'   r(   )r   pause_playbackr
   r-   r.   r   r   r   r   pause      $r   c               
   C   r   )	zResume playback.r   u   Resumed. — Lukeru   Nu.   No active device. Open Spotify first. — LukezResume error: r'   r(   )r   ry   r
   r-   r   r   r   r   resume	  r   r   c               
   C   sn   t  } | sdS z|   ddl}|d t W S  ty6 } zdt|dd  dW  Y d}~S d}~ww )zSkip to next track.r   r   Ng      ?zSkip error: r'   r(   )r   
next_tracktimesleepr4   r
   r-   )r.   r   r   r   r   r   skip  s   
$r   c              
   C   s   t  }|sdS zB|j| ddd}|di dg }|s#d|  dW S |d	 }|d
 }ddd |dg D }||d  d| d| dW S  tyg } zdt|dd  dW  Y d}~S d}~ww )z+Search for a track and add it to the queue.r   r0   rS   rg   rk   r8   zCouldn't find '   '. — Luker   r   r   c                 s   r   r   r   r   r   r   r   r   7  r   zadd_to_queue.<locals>.<genexpr>r   rl   zQueued: rt   r(   zQueue error: Nr'   )r   rw   r*   r+   add_to_queuer
   r-   )rz   r.   r}   rk   r0   r   r   r   r   r   r   r   (  s"   $r   c              
   C   sH  t  }|sdS zq|jdd}|dg D ]&}|  |d  v r:|j|d d d|d  d	|d
 d  d  W S q|j| ddd}|di dg }|rr|d }|j|d d d|d  d|d d  d	|d
 d  dW S d|  dW S  ty } zdt|v rW Y d}~dS dt|dd  dW  Y d}~S d}~ww )z.Find and play one of Bill's playlists by name.r   2   r6   r8   r   rl   )rn   zPlaying your playlist: ro   rk   rp   rq   playlistrf   rg   rj   r   rs   rt   ownerdisplay_namezNo playlist found matching 'r   ru   Nu6   No active Spotify device. Open Spotify first. — LukezPlaylist error: r'   r(   )r   current_user_playlistsr*   rx   ry   rw   r
   r-   )r   r.   rj   r~   r}   r8   r   r   r   r   play_playlist?  s.   $.$r      c                 C   sp  t  }|sdS zddlm} i }z|jdd}|di dg D ]
}|d ||d	 < q"W n	 ty7   Y nw z|jd
dd}|dg D ]
}|d ||d	 < qFW n	 ty[   Y nw z|jddd}|dg D ]
}|d ||d	 < qjW n	 ty   Y nw |sW dS t |dd d}g }	|	 D ]Z\}
}zD|j
|
dddd}|dg D ]2}|dd}||kr|di dd}|dd}|dd}|	||dd||||d qW n	 ty   Y qw t|	| kr nq|	sW dS t }g }|	D ]}|d   d!|d   }||vr|| || q|jd"d# d$d% d&dg}|t| d't|d(kr:d)nd d* |d |D ]C}|d+ dkrRd,nd-}|d.|d   d/|d   |d0| d1|d2  d3|d4   |d5 r|d0|d5   |d qGd6|W S  ty } ztd7|  d8t|d9d:  d;W  Y d9}~S d9}~ww )<uk  
    Check for new releases from artists Bill follows or listens to.
    Music drops on Fridays — Luke runs this Friday morning.

    Checks:
      1. Artists Bill follows
      2. Bill's top artists (last 6 months)
    Then finds any albums/singles released in the last 7 days.

    Returns formatted text with album links, or empty string if nothing new.
    r   r   )	timedeltar   r6   r   r8   r   re      rH   rI   r   rP   uI   No followed or top artists found yet. Listen more and try again. — Luke   )daysz%Y-%m-%dzalbum,singler5   CA)
album_typer7   countryrelease_dater    external_urlsr   r   r   total_tracks)r]   r   ri   rk   dateurlu2   No new drops from your artists this week. — Luker]   r#   c                 S   s   | d dkrdnd| d fS )Nri   r   r   rS   r   r   )xr   r   r   <lambda>  s    znew_releases.<locals>.<lambda>T)keyreverseu   NEW MUSIC FRIDAY — Lukez new releaserS   sz from your artists:ri   ALBUMSINGLEr;   r<   r=   ro   rk   u    tracks) • Released r   r   r&   zNew releases error: zCouldn't check new releases: Nr'   r(   )r   r   r   current_user_followed_artistsr*   r
   rX   nowrA   r8   artist_albumsr,   lensetrx   addsortr+   r   r   r-   )r7   r.   r   
artist_idsfollowedr]   top
top_recentcutoff	new_drops	artist_idr   albumsr   r   	album_urlr   r   seenuniquedropr   r3   
type_labelr   r   r   r   new_releases]  s   



,
$
$r   c              
   C   s,  t  }|sdS zs|j| dd}|dg }|sW dS dg}t|dD ]R\}}|dd}d	d
d |dg D }|di }	|	dd}
|	di dd}d| d| d| }|
re|d|
 d7 }|| |rt|d|  q"d|W S  ty } ztd|  W Y d}~dS d}~ww )z
    Get Bill's top tracks from the past 4 weeks with Spotify album links.
    Used in the weekly report.

    Returns a formatted text block or empty string if unavailable.
    r    rP   rI   r8   zYOUR WEEK IN MUSICrS   r   r   r   c                 s   r   r   r   r   r   r   r   r     r   z'weekly_music_summary.<locals>.<genexpr>r   r   r   r   r;   rV   r<   ro   )rW   r&   zWeekly music summary error: N)	r   r_   r*   rY   r+   r,   r
   r   r   )r7   r.   rZ   r8   r3   r\   r0   r   r   r   
album_namer   liner   r   r   r   weekly_music_summary  s8   
r   c                   C   s   t  tt  p	tdu dS )z.Get Spotify status for dashboard health check.N)	available
configured)r   boolr   r   r   r   r   
get_status  s   r   )r5   )rH   r5   )r   )__doc__loggingr   	getLoggerr   r   r   r   r   r4   rG   r^   r`   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s*    

'
%
% 5

v*