
    iL                       d Z ddlmZ ddlmZmZmZ ddlmZ ddl	m
Z
mZmZmZmZmZmZ ddlmZmZ d_d	Zd`dZdadZdddddbdZdcdddZdedZdfd"Zdgd%Zdgd&Zdgd'Zdgd(Zdgd)Zdgd*Z dgd+Z!d,d-iZ"d.d/d0d-g d1d2e"e"e"d3e"d4d,d0id,d5id6d,d-id,d7igd8d,d5id5d9d:d5d;d:d5d<d:d=d gd>d?Z#d@dAd0d-dBdCgd2e"d,d7idDd gd>d?Z$dEdFd0d-dGdHgd2e"e"dId gd>d?Z%dJdKd0e"d3e"d4e"d,d5id,d5ie"e"dLdMgd>d?Z&dNdOd0d-g dPd2e"e"d,d5id,d5ie"e"d,d7id,d7id3e"d4d,d5ie"dQd gd>d?Z'dRdSd0d-dGdTgd2e"e"e"d,d5id,d5idUd gd>d?Z(dVdWd0d-dTdXgdYdZd-g d[d2d,d5id,d5ie"d3e"d4d3e"d4d3e"d4d\d]d gd>d?Z)d^S )hzANative Spotify tools for Hermes (registered via plugins/spotify).    )annotations)AnyDictList)get_auth_status)SpotifyAPIErrorSpotifyAuthRequiredErrorSpotifyClientSpotifyErrornormalize_spotify_idnormalize_spotify_urinormalize_spotify_uris)
tool_errortool_resultreturnboolc                     	 t          t          d                              d                    S # t          $ r Y dS w xY w)Nspotify	logged_inF)r   r   get	Exception     :/home/ubuntu/.hermes/hermes-agent/plugins/spotify/tools.py_check_spotify_availabler      sM    OI..22;??@@@   uus   .1 
??r
   c                     t                      S N)r
   r   r   r   _spotify_clientr      s    ??r   excr   strc                0   t          | t          t          f          rt          t	          |                     S t          | t
                    r#t          t	          |           | j                  S t          dt          |           j         d|            S )N)status_codezSpotify tool failed: z: )	
isinstancer   r	   r   r    r   r"   type__name__)r   s    r   _spotify_tool_errorr&      s    #&>?@@ $#c((####'' A#c((@@@@Id3ii.@IICIIJJJr         2   )defaultminimummaximumrawr   r*   intr+   r,   c                   	 t          |           }n# t          $ r |}Y nw xY wt          |t          ||                    S r   )r.   r   maxmin)r-   r*   r+   r,   values        r   _coerce_limitr3   '   sR    C   wGU++,,,s    !!Fc                    t          | t                    r| S t          | t                    r2|                                                                 }|dv rdS |dv rdS |S )N>   1onyestrueT>   0noofffalseF)r#   r   r    striplower)r-   r*   cleaneds      r   _coerce_boolr@   /   sk    #t 
#s ))++##%%00041115Nr   	List[str]c                    | g S t          | t                    rd | D             S t          |                                           r"t          |                                           gng S )Nc                    g | ]D}t          |                                          #t          |                                          ES r   )r    r=   ).0items     r   
<listcomp>z_as_list.<locals>.<listcomp>?   s=    GGGdSYY__5F5FGD		!!GGGr   )r#   listr    r=   )r-   s    r   _as_listrH   ;   sf    
{	#t HGGcGGGG!$S!1!19CHHNNr9r   payloadactiondict | Nonec               :   t          | t                    r|                     d          sd S |dk    r1d|d|                     dd          |                     d          pdd	S |d
k    r1d|d|                     dd          |                     d          pddS d S )Nemptyget_currently_playingTFr"      messagez*Spotify is not currently playing anything.)successrJ   
is_playingr"   rP   	get_statez-No active Spotify playback session was found.)rQ   rJ   has_active_devicer"   rP   )r#   dictr   )rI   rJ   s     r   _describe_empty_playbackrV   C   s    gt$$ GKK,@,@ t(((";;}c::{{9--]1]
 
 	
 !&";;}c::{{9--`1`
 
 	
 4r   argsrU   c                ~   t          |                     d          pd                                                                          }t	                      }	 |dk    rK|                    |                     d                    }t          ||          }t          |p|          S |dk    rK|                    |                     d                    }t          ||          }t          |p|          S |dk    r|                     d          }t          |t                    rd	 |                                D             }nd }|                     d
          r0t          t          |                     d
                    d          nd }d }	|                     d          rt          |                     d                    }
d }|
                    d          sd|
v rd}n7|
                    d          sd|
v rd}n|
                    d          sd|
v rd}t          |
|          }	|                    |                     d          |	|||                     d                    }t          d||d          S |dk    r<|                    |                     d                    }t          d||d          S |dk    r<|                    |                     d                    }t          d||d          S |dk    r<|                    |                     d                    }t          d||d          S |dk    rt|                     d          t)          d           S |                    t-          | d                   |                     d          !          }t          d||d          S |d"k    rt          |                     d#          pd$                                                                          }|d%vrt)          d&          S |                    ||                     d          '          }t          d||d          S |d(k    r]|                    t3          |                     d#                    |                     d          '          }t          d||d          S |d)k    r|                     d*          t)          d+          S |                    t7          d,t9          d-t-          | d*                                       |                     d          .          }t          d||d          S |d/k    r|                     d0          }|                     d1          }|r|rt)          d2          S t          |                    t=          |                     d3          d45          |t-          |          nd |t-          |          nd 6                    S t)          d7|           S # t>          $ r}tA          |          cY d }~S d }~ww xY w)8NrJ   rS   market)rY   )rJ   rN   playoffsetc                    i | ]
\  }}|||S r   r   )rD   kvs      r   
<dictcomp>z,_handle_spotify_playback.<locals>.<dictcomp>h   s    !S!S!S41aQ]!Q]]]r   uristrackcontext_urizspotify:album:z/album/albumzspotify:playlist:z
/playlist/playlistzspotify:artist:z/artist/artist	device_idposition_ms)rf   rb   r`   r[   rg   TrQ   rJ   resultpause)rf   nextpreviousseekz)position_ms is required for action='seek')rg   rf   
set_repeatstate >   r;   ra   contextz)state must be one of: track, context, off)ro   rf   set_shuffle
set_volumevolume_percentz2volume_percent is required for action='set_volume'r   d   )rt   rf   recently_playedafterbeforez'Provide only one of 'after' or 'before'limitr'   r*   )ry   rw   rx   z!Unknown spotify_playback action: )!r    r   r=   r>   r   get_playback_staterV   r   rN   r#   rU   itemsr   rH   
startswithr   start_playbackpause_playback	skip_nextskip_previousr   rm   r.   rn   rr   r@   rs   r0   r1   get_recently_playedr3   r   r&   )rW   kwrJ   clientrI   empty_resultr[   payload_offsetr`   rb   raw_contextcontext_typeri   ro   rw   rx   r   s                    r   _handle_spotify_playbackr   Y   s   (##2{3399;;AACCFFK([  //txx7I7I/JJG3GFKKKL|6w777,,,22$((8:L:L2MMG3GFKKKL|6w777VXXh''F&$'' &!S!S6<<>>!S!S!S!%RVRZRZ[aRbRbl)(488F3C3C*D*DgNNNhlDKxx&& 	O!$((="9"9::#))*:;; ,yK?W?W#*LL ++,?@@ ,LT_D_D_#-LL ++,=>> ,*P[B[B[#+L3KNN**((;//'% HH]33 +  F 46VTTUUUW**TXXk5J5J*KKF46VTTUUUV%%0E0E%FFF46VTTUUUZ))DHH[4I4I)JJF46VTTUUUVxx&&.!"MNNN[[Sm1D-E-EQUQYQYZeQfQf[ggF46VTTUUU\!!))/R006688>>@@E777!"MNNN&&Udhh{>S>S&TTF46VTTUUU]""''l488G;L;L.M.MY]YaYabmYnYn'ooF46VTTUUU\!!xx())1!"VWWW&&c!Sc$O_J`FaFa=b=b6c6cosowow  yD  pE  pE&  F  FF46VTTUUU&&&HHW%%EXXh''F M M!"KLLLv99#DHHW$5$5rBBB$)$5c%jjj4&,&8s6{{{d  :       
 FfFFGGG ( ( ("3''''''''(s   AX )AX :F	X AX AX AX 
)X 4AX A X %<X "A"X )X /A+X AX A(X X 
X<#X71X<7X<c                   t          |                     d          pd                                                                          }t	                      }	 |dk    r!t          |                                          S |dk    rt          |                     d          pd                                          }|st          d          S |                    |t          |                     d                              }t          d	||d
          S t          d|           S # t          $ r}t          |          cY d }~S d }~ww xY w)NrJ   rG   transferrf   rp   z+device_id is required for action='transfer'rZ   )rf   rZ   Trh   z Unknown spotify_devices action: )r    r   r=   r>   r   r   get_devicesr   transfer_playbackr@   r   r&   )rW   r   rJ   r   rf   ri   r   s          r   _handle_spotify_devicesr      sU   (##-v..4466<<>>FF(Vv1133444ZDHH[117R88>>@@I Q!"OPPP--	UYU]U]^dUeUeHfHf-ggF46VTTUUUEVEEFFF ( ( ("3''''''''(s2   &D( ?AD( A	D( D( (
E2E EEc                Z   t          |                     d          pd                                                                          }t	                      }	 |dk    r!t          |                                          S |dk    rpt          t          |                     d          pd          d           }|                    ||                     d                    }t          d|||d	          S t          d
|           S # t          $ r}t          |          cY d }~S d }~ww xY w)NrJ   r   addurirp   rf   )r   rf   T)rQ   rJ   r   ri   zUnknown spotify_queue action: )r    r   r=   r>   r   r   	get_queuer   add_to_queuer   r   r&   )rW   r   rJ   r   r   ri   r   s          r   _handle_spotify_queuer      s,   (##,u--3355;;==FF	(U??v//11222U??'DHHUOO,Ar(B(BDIIC((SDHH[<Q<Q(RRF46#Y_``aaaC6CCDDD ( ( ("3''''''''(s+   &D ?A5D 5D 
D*D%D*%D*c                   t                      }t          |                     d          pd                                          }|st	          d          S t          |                     d          p|                     d          pdg          }d |D             }|st	          d          S 	 t          |                    ||t          |                     d	          d
          t          dt          |                     d          pd                    |                     d          |                     d                              S # t          $ r}t          |          cY d }~S d }~ww xY w)Nqueryrp   zquery is requiredtypesr$   ra   c                b    g | ],}|                                 d v |                                 -S )>   showrc   ra   re   episoderd   	audiobook)r>   )rD   r2   s     r   rF   z*_handle_spotify_search.<locals>.<listcomp>   sO      W  W  WeEKKMM  NV  =V  =VEKKMM  =V  =V  =Vr   z[types must contain one or more of: album, artist, playlist, track, show, episode, audiobookry   
   rz   r   r[   rY   include_external)r   search_typesry   r[   rY   r   )r   r    r   r=   r   rH   r   searchr3   r0   r.   r   r&   )rW   r   r   r   	raw_typesr   r   s          r   _handle_spotify_searchr      s   F!!'R((..00E /-...'**Kdhhv.>.>K7)LLI W  Wy  W  W  WL ywxxx
(6==% 1 12>>>q#dhhx005A667788H%%!XX&899 ) 
 
   	  ( ( ("3''''''''(s   .BE 
E1E,&E1,E1c                T   t          |                     d          pd                                                                          }t	                      }	 |dk    rvt          |                    t          |                     d          d          t          dt          |                     d          pd                                        S |d	k    rit          t          |                     d
          pd          d          }t          |                    ||                     d                              S |dk    rt          |                     d          pd                                          }|st          d          S t          |                    |t          |                     d                    t          |                     d                    |                     d                              S |dk    rt          t          |                     d
          pd          d          }t          t!          |                     d                              }t          |                    |||                     d                              S |dk    rt          t          |                     d
          pd          d          }t          t!          |                     d                              }t          |                    |||                     d                              S |dk    rt          t          |                     d
          pd          d          }t          |                    ||                     d          |                     d          |                     d          |                     d                              S t          d|           S # t(          $ r}t+          |          cY d }~S d }~ww xY w) NrJ   rG   ry   r'   rz   r   r[   )ry   r[   r   playlist_idrp   rd   rY   )r   rY   createnamez$name is required for action='create'publiccollaborativedescription)r   r   r   r   	add_itemsr`   position)r   r`   r   remove_itemssnapshot_id)r   r`   r   update_details)r   r   r   r   r   z"Unknown spotify_playlists action: )r    r   r=   r>   r   r   get_my_playlistsr3   r0   r.   r   get_playlistr   create_playlistr@   r   rH   add_playlist_itemsremove_playlist_itemsupdate_playlist_detailsr   r&   )rW   r   rJ   r   r   r   r`   r   s           r   _handle_spotify_playlistsr      s   (##-v..4466<<>>FF.(Vv66#DHHW$5$5rBBB1c$((8"4"4"9::;;  7        U??.s488M3J3J3Pb/Q/QS]^^Kv22{SWS[S[\dSeSe2ffgggXtxx''-2..4466D J!"HIIIv55#DHHX$6$677*488O+D+DEE HH]33	  6        [  .s488M3J3J3Pb/Q/QS]^^K)(488F3C3C*D*DEEDv88'*--  9       
 ^##.s488M3J3J3Pb/Q/QS]^^K)(488F3C3C*D*DEEDv;;' HH]33  <       
 %%%.s488M3J3J3Pb/Q/QS]^^Kv=='XXf%%xx))"hh77 HH]33  >        GvGGHHH ( ( ("3''''''''(sO   A;P A.P AP A8P 	BP (BP B*P 2P 
P'P"P'"P'c                J   t          |                     d          pd                                                                          }t	                      }	 t          t          |                     d          p|                     d          pd          d          }|dk    r7t          |                    ||                     d                              S |d	k    rt          |                    |t          |                     d
          d          t          dt          |                     d          pd                    |                     d                              S t          d|           S # t          $ r}t          |          cY d }~S d }~ww xY w)NrJ   r   album_ididrp   rc   rY   )r   rY   tracksry   r'   rz   r   r[   )r   ry   r[   rY   zUnknown spotify_albums action: )r    r   r=   r>   r   r   r   	get_albumget_album_tracksr3   r0   r.   r   r   r&   )rW   r   rJ   r   r   r   s         r   _handle_spotify_albumsr     s   (##,u--3355;;==FF('DHHZ,@,@,XDHHTNN,XVX(Y(Y[bccU??v//$((S[J\J\/]]^^^Xv66!#DHHW$5$5rBBB1c$((8"4"4"9::;;xx))	  7        DFDDEEE ( ( ("3''''''''(s,   BE? BE? -E? ?
F"	FF"F"c                   t          |                     d          pd                                                                          }|dvrt	          d          S t          |                     d          pd                                                                          }|dk    rdnd	t                      }	 |dk    rt          |                     d
          d          }t          dt          |                     d          pd                    }|                     d          }|dk    r%t          |
                    |||                    S t          |                    |||                    S |dk    rht          t          |                     d          p|                     d                              }t          |                    |                    S |dk    rfdt          |                     d          p|                     d                    D             }	|	st	          d          S |dk    r#t          |                    |	                    S t          |                    |	                    S t	          d|           S # t"          $ r}
t%          |
          cY d}
~
S d}
~
ww xY w)zEUnified handler for saved tracks + saved albums (formerly two tools).kindrp   >   albumsr   z#kind must be one of: tracks, albumsrJ   rG   r   ra   rc   ry   r'   rz   r   r[   rY   )ry   r[   rY   saver`   r|   )r`   removec                0    g | ]}t          |          S r   )r   )rD   rE   	item_types     r   rF   z+_handle_spotify_library.<locals>.<listcomp>;  s$    tttT'i88tttr   idsz)ids/items is required for action='remove')	track_ids)	album_idsz Unknown spotify_library action: N)r    r   r=   r>   r   r   r3   r0   r.   r   get_saved_tracksget_saved_albumsr   rH   save_library_itemsremove_saved_tracksremove_saved_albumsr   r&   )rW   r   r   rJ   r   ry   r[   rY   r`   r   r   r   s              @r   _handle_spotify_libraryr   '  s   txx%2&&,,..4466D'''?@@@(##-v..4466<<>>F8++IF(V!$((7"3"3R@@@EC 2 2 7a8899FXXh''Fx"6#:#:v^d#:#e#efffv66U6Z`6aabbbV)(488F3C3C3XtxxPWGXGX*Y*Y[deeDv88d8CCDDDXttttXdhhW\ooNraeaiaijqararEsEstttC O!"MNNNx"6#=#=#=#L#LMMMv99C9HHIIIEVEEFFF ( ( ("3''''''''(sE   >BJ% $J% ?A-J% -AJ% (J% 0"J% J% %
K/K=KKr$   stringspotify_playbackz]Control Spotify playback, inspect the active playback state, or fetch recently played tracks.object)rS   rN   rZ   rj   rk   rl   rm   rn   rr   rs   rv   )r$   enumarray)r$   r|   integerzRFor set_repeat use track/context/off. For set_shuffle use boolean-like true/false.boolean)r   oneOfz.For recently_played: number of tracks (max 50))r$   r   z:For recently_played: Unix ms cursor (after this timestamp)z;For recently_played: Unix ms cursor (before this timestamp))rJ   rf   rY   rb   r`   r[   rg   ro   rt   ry   rw   rx   )r$   
propertiesrequired)r   r   
parametersspotify_deviceszHList Spotify Connect devices or transfer playback to a different device.rG   r   )rJ   rf   rZ   spotify_queuez6Inspect the user's Spotify queue or add an item to it.r   r   )rJ   r   rf   spotify_searchzVSearch the Spotify catalog for tracks, albums, artists, playlists, shows, or episodes.)r   r   r$   ry   r[   rY   r   r   spotify_playlistsz<List, inspect, create, update, and modify Spotify playlists.)rG   r   r   r   r   r   )rJ   r   rY   ry   r[   r   r   r   r   r`   r   r   spotify_albumsz-Fetch Spotify album metadata or album tracks.r   )rJ   r   r   rY   ry   r[   spotify_libraryz\List, save, or remove the user's saved Spotify tracks or albums. Use `kind` to select which.r   zWhich library to operate on)r$   r   r   )rG   r   r   )r   rJ   ry   r[   rY   r`   r   r|   r   N)r   r   )r   r
   )r   r   r   r    )
r-   r   r*   r.   r+   r.   r,   r.   r   r.   )F)r-   r   r*   r   r   r   )r-   r   r   rA   )rI   r   rJ   r    r   rK   )rW   rU   r   r    )*__doc__
__future__r   typingr   r   r   hermes_cli.authr   plugins.spotify.clientr   r	   r
   r   r   r   r   tools.registryr   r   r   r   r&   r3   r@   rH   rV   r   r   r   r   r   r   r   COMMON_STRINGSPOTIFY_PLAYBACK_SCHEMASPOTIFY_DEVICES_SCHEMASPOTIFY_QUEUE_SCHEMASPOTIFY_SEARCH_SCHEMASPOTIFY_PLAYLISTS_SCHEMASPOTIFY_ALBUMS_SCHEMASPOTIFY_LIBRARY_SCHEMAr   r   r   <module>r      sT   G G " " " " " " " " " " " " " " " " + + + + + +                  3 2 2 2 2 2 2 2      K K K K /1SU - - - - - -	 	 	 	 	: : : :   ,N( N( N( N(b( ( ( ("( ( ( (( ( ( (,1( 1( 1( 1(h( ( ( (&( ( ( (> " r'  2C  2C  2C  D  D&#($}==x("I.%y  GM  OW  FX  [a  cl  Zm  En  o  o%y1'8hii'8tuu(9vww
 
 J!   0 ]'&*1EFF&Y'
 

 J    K'%@@ &
 

 J    k"%>>!i(y)# -
 
 I   &  Q'1y1y1yzz(#i(y)!(y)$i0$}==+(
 
 J!   0 B'%1BCC%#i(y)
 
 J   $ q%(/CTqrr'1K1K1KLLi(y)#$}==#m<<%>>	
 	
 X&     r   