
    `gjL                       d Z ddlmZ ddl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 dMdZdNdZdOd	Zd
ddddPdZdQdRdZdSdZdTdZdUdZdUdZdUdZdUdZdUdZdUdZdUdZ ddiZ!ddddg dd e!e!e!d!e!d"ddidd#id$ddidd%igd&dd#id#d'd(d#d)d(d#d*d(d+dgd,d-Z"d.d/ddd0d1gd e!dd%id2dgd,d-Z#d3d4ddd5d6gd e!e!d7dgd,d-Z$d8d9de!d!e!d"e!dd#idd#ie!e!d:d;gd,d-Z%d<d=ddg d>d e!e!dd#idd#ie!e!dd%idd%id!e!d"dd#ie!d?dgd,d-Z&d@dAddd5dBgd e!e!e!dd#idd#idCdgd,d-Z'dDdEdddBdFgdGdHdg dId dd#idd#ie!d!e!d"d!e!d"d!e!d"dJdKdgd,d-Z(yL)VzANative Spotify tools for Hermes (registered via plugins/spotify).    )annotations)AnyList)get_auth_status)SpotifyAPIErrorSpotifyAuthRequiredErrorSpotifyClientSpotifyErrornormalize_spotify_idnormalize_spotify_urinormalize_spotify_uris)
tool_errortool_resultc                 h    	 t        t        d      j                  d            S # t        $ r Y yw xY w)Nspotify	logged_inF)boolr   get	Exception     H/root/.hermes/venv/lib/python3.12/site-packages/plugins/spotify/tools.py_check_spotify_availabler      s4    OI.22;?@@ s   "% 	11c                     t               S N)r	   r   r   r   _spotify_clientr      s
    ?r   c                    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   strr   r   type__name__)excs    r   _spotify_tool_errorr$      sd    #&>?@#c(###'#c(@@-d3i.@.@-AC5IJJr         2   )defaultminimummaximumc               h    	 t        |       }t        |t        ||            S # t        $ r |}Y #w xY wr   )intr   maxmin)rawr(   r)   r*   values        r   _coerce_limitr1   '   s<    C wGU+,,  s   # 11c                    t        | t              r| S t        | t              r(| j                         j	                         }|dv ry|dv ry|S )N>   1onyestrueT>   0noofffalseF)r   r   r    striplower)r/   r(   cleaneds      r   _coerce_boolr>   /   sL    #t
#s))+##%0011Nr   c                    | g S t        | t              rA| D cg c]5  }t        |      j                         st        |      j                         7 c}S t        |       j                         rt        |       j                         gS g S c c}w r   )r   listr    r;   )r/   items     r   _as_listrB   ;   sk    
{	#t.1GdSY__5FD	!GG!$S!1CHNN9r9 Hs
   BBactionc                  t        | t              r| j                  d      sy |dk(  r+d|d| j                  dd      | j                  d      xs dd	S |d
k(  r+d|d| j                  dd      | j                  d      xs ddS y )Nemptyget_currently_playingTFr      messagez*Spotify is not currently playing anything.)successrC   
is_playingr   rH   	get_statez-No active Spotify playback session was found.)rI   rC   has_active_devicer   rH   )r   dictr   )payloadrC   s     r   _describe_empty_playbackrO   C   s    gt$GKK,@((";;}c:{{9-]1]
 	
 !&";;}c:{{9-`1`
 	
 r   c                
   t        | j                  d      xs d      j                         j                         }t	               }	 |dk(  r=|j                  | j                  d            }t        ||      }t        |xs |      S |dk(  r=|j                  | j                  d            }t        ||      }t        |xs |      S |dk(  rF| j                  d      }t        |t              r'|j                         D ci c]  \  }}|	|| }	}}nd }	| j                  d	      r$t        t        | j                  d	            d
      nd }
d }| j                  d      rot        | j                  d            }d }|j                  d      sd|v rd}n/|j                  d      sd|v rd}n|j                  d      sd|v rd}t        ||      }|j!                  | j                  d      ||
|	| j                  d            }t        d||d      S |dk(  r0|j#                  | j                  d            }t        d||d      S |dk(  r0|j%                  | j                  d            }t        d||d      S |dk(  r0|j'                  | j                  d            }t        d||d      S |dk(  rY| j                  d      t)        d      S |j+                  t-        | d         | j                  d             }t        d||d      S |d!k(  rzt        | j                  d"      xs d#      j                         j                         }|d$vrt)        d%      S |j/                  || j                  d      &      }t        d||d      S |d'k(  rI|j1                  t3        | j                  d"            | j                  d      &      }t        d||d      S |d(k(  rm| j                  d)      t)        d*      S |j5                  t7        d+t9        d,t-        | d)                     | j                  d      -      }t        d||d      S |d.k(  r| j                  d/      }| j                  d0      }|r|rt)        d1      S t        |j;                  t=        | j                  d2      d34      |t-        |      nd |t-        |      nd 5            S t)        d6|       S c c}}w # t>        $ r}tA        |      cY d }~S d }~ww xY w)7NrC   rK   market)rQ   )rC   rF   playoffseturistrackcontext_urizspotify:album:z/album/albumzspotify:playlist:z
/playlist/playlistzspotify:artist:z/artist/artist	device_idposition_ms)rZ   rV   rT   rS   r[   TrI   rC   resultpause)rZ   nextpreviousseekz)position_ms is required for action='seek')r[   rZ   
set_repeatstate >   r9   rU   contextz)state must be one of: track, context, off)rc   rZ   set_shuffle
set_volumevolume_percentz2volume_percent is required for action='set_volume'r   d   )rh   rZ   recently_playedafterbeforez'Provide only one of 'after' or 'before'limitr%   r(   )rm   rk   rl   z!Unknown spotify_playback action: )!r    r   r;   r<   r   get_playback_staterO   r   rF   r   rM   itemsr   rB   
startswithr   start_playbackpause_playback	skip_nextskip_previousr   ra   r,   rb   rf   r>   rg   r-   r.   get_recently_playedr1   r   r$   )argskwrC   clientrN   empty_resultrS   kvpayload_offsetrT   rV   raw_contextcontext_typer]   rc   rk   rl   r#   s                      r   _handle_spotify_playbackr   Y   s   (#2{399;AACFFK([ //txx7I/JG3GFKL|6w77,,22$((8:L2MG3GFKL|6w77VXXh'F&$'39<<>!S41aQ]!Q$!S!S!%RVRZRZ[aRb)(488F3C*DgNhlDKxx&!$((="9:#))*:;yK?W#*L ++,?@LT_D_#-L ++,=>*P[B[#+L3KN**((;/'% HH]3 + F 46VTUUW**TXXk5J*KF46VTUUV%%0E%FF46VTUUZ))DHH[4I)JF46VTUUVxx&.!"MNN[[Sm1D-EQUQYQYZeQf[gF46VTUU\!)/R0668>>@E77!"MNN&&Udhh{>S&TF46VTUU]"''l488G;L.MY]YaYabmYn'oF46VTUU\!xx()1!"VWW&&c!Sc$O_J`Fa=b6cosowow  yD  pE&  FF46VTUU&&HHW%EXXh'F!"KLLv99#DHHW$5rB$)$5c%j4&,&8s6{d  :    
 =fXFGG{ "T|  ("3''(s   AS- AS- 
:S- 
S'S'DS- 4S- 4S-  4S- 5 S- <S- AS- !0S- AS-   S- AS- 5S- AS- S- 'S- -	T6
T TTc                   t        | j                  d      xs d      j                         j                         }t	               }	 |dk(  rt        |j                               S |dk(  rst        | j                  d      xs d      j                         }|st        d      S |j                  |t        | j                  d                  }t        d	||d
      S t        d|       S # t        $ r}t        |      cY d }~S d }~ww xY w)NrC   r@   transferrZ   rd   z+device_id is required for action='transfer'rR   )rZ   rR   Tr\   z Unknown spotify_devices action: )r    r   r;   r<   r   r   get_devicesr   transfer_playbackr>   r   r$   )rw   rx   rC   ry   rZ   r]   r#   s          r   _handle_spotify_devicesr      s    (#-v.446<<>FF(Vv11344ZDHH[17R8>>@I!"OPP--	UYU]U]^dUeHf-gF46VTUU<VHEFF ("3''(s0   C* $=C* "9C* C* *	D3
D=DDc                   t        | j                  d      xs d      j                         j                         }t	               }	 |dk(  rt        |j                               S |dk(  rZt        t        | j                  d      xs d      d       }|j                  || j                  d            }t        d|||d	      S t        d
|       S # t        $ r}t        |      cY d }~S d }~ww xY w)NrC   r   addurird   rZ   )r   rZ   T)rI   rC   r   r]   zUnknown spotify_queue action: )r    r   r;   r<   r   r   	get_queuer   add_to_queuer   r   r$   )rw   rx   rC   ry   r   r]   r#   s          r   _handle_spotify_queuer      s    (#,u-335;;=FF	(U?v//122U?'DHHUO,Ar(BDIC((SDHH[<Q(RF46#Y_`aa:6(CDD ("3''(s+   C $AC C 	C/
C*$C/*C/c                   t               }t        | j                  d      xs d      j                         }|st	        d      S t        | j                  d      xs | j                  d      xs dg      }|D cg c]%  }|j                         dv s|j                         ' }}|st	        d      S 	 t        |j                  ||t        | j                  d	      d
      t        dt        | j                  d      xs d            | j                  d      | j                  d                  S c c}w # t        $ r}t        |      cY d }~S d }~ww xY w)Nqueryrd   zquery is requiredtypesr!   rU   >   showrW   rU   rY   episoderX   	audiobookz[types must contain one or more of: album, artist, playlist, track, show, episode, audiobookrm   
   rn   r   rS   rQ   include_external)r   search_typesrm   rS   rQ   r   )r   r    r   r;   r   rB   r<   r   searchr1   r-   r,   r   r$   )rw   rx   ry   r   	raw_typesr0   r   r#   s           r   _handle_spotify_searchr      s<   F!'R(..0E-..'*Kdhhv.>K7)LI/8  WeEKKM  NV  =VEKKM  WL  Wwxx
(6==% 12>q#dhhx05A6788H%!XX&89 ) 
  		 W  ("3''(s+   :D2D24A=D7 7	E 
E
EEc                   t        | j                  d      xs d      j                         j                         }t	               }	 |dk(  r\t        |j                  t        | j                  d      d      t        dt        | j                  d      xs d                        S |d	k(  rSt        t        | j                  d
      xs d      d      }t        |j                  || j                  d                  S |dk(  rt        | j                  d      xs d      j                         }|st        d      S t        |j                  |t        | j                  d            t        | j                  d            | j                  d                  S |dk(  rwt        t        | j                  d
      xs d      d      }t        t!        | j                  d                  }t        |j#                  ||| j                  d                  S |dk(  rwt        t        | j                  d
      xs d      d      }t        t!        | j                  d                  }t        |j%                  ||| j                  d                  S |dk(  rt        t        | j                  d
      xs d      d      }t        |j'                  || j                  d      | j                  d      | j                  d      | j                  d                  S t        d|       S # t(        $ r}t+        |      cY d }~S d }~ww xY w) NrC   r@   rm   r%   rn   r   rS   )rm   rS   r   playlist_idrd   rX   rQ   )r   rQ   createnamez$name is required for action='create'publiccollaborativedescription)r   r   r   r   	add_itemsrT   position)r   rT   r   remove_itemssnapshot_id)r   rT   r   update_details)r   r   r   r   r   z"Unknown spotify_playlists action: )r    r   r;   r<   r   r   get_my_playlistsr1   r-   r,   r   get_playlistr   create_playlistr>   r   rB   add_playlist_itemsremove_playlist_itemsupdate_playlist_detailsr   r$   )rw   rx   rC   ry   r   r   rT   r#   s           r   _handle_spotify_playlistsr      s   (#-v.446<<>FF.(Vv66#DHHW$5rB1c$((8"4"9:;  7     U?.s488M3J3Pb/QS]^Kv22{SWS[S[\dSe2fggXtxx'-2.446D!"HIIv55#DHHX$67*488O+DE HH]3	  6     [ .s488M3J3Pb/QS]^K)(488F3C*DEDv88'*-  9    
 ^#.s488M3J3Pb/QS]^K)(488F3C*DEDv;;' HH]3  <    
 %%.s488M3J3Pb/QS]^Kv=='XXf%xx)"hh7 HH]3  >     >vhGHH ("3''(sN   A L( 'AL( ?=L( =AL( A;L( A;L( BL( L( (	M1
M;MMc                   t        | j                  d      xs d      j                         j                         }t	               }	 t        t        | j                  d      xs | j                  d      xs d      d      }|dk(  r+t        |j                  || j                  d                  S |d	k(  rmt        |j                  |t        | j                  d
      d      t        dt        | j                  d      xs d            | j                  d                  S t        d|       S # t        $ r}t        |      cY d }~S d }~ww xY w)NrC   r   album_ididrd   rW   rQ   )r   rQ   tracksrm   r%   rn   r   rS   )r   rm   rS   rQ   zUnknown spotify_albums action: )r    r   r;   r<   r   r   r   	get_albumget_album_tracksr1   r-   r,   r   r   r$   )rw   rx   rC   ry   r   r#   s         r   _handle_spotify_albumsr     s)   (#,u-335;;=FF('DHHZ,@,XDHHTN,XVX(Y[bcU?v//$((S[J\/]^^Xv66!#DHHW$5rB1c$((8"4"9:;xx)	  7     ;F8DEE ("3''(s,   A*D1 1A1D1 #D1 1	E:
E
E
Ec                   t        | j                  d      xs d      j                         j                         }|dvrt	        d      S t        | j                  d      xs d      j                         j                         }|dk(  rdnd	}t               }	 |dk(  rt        | j                  d
      d      }t        dt        | j                  d      xs d            }| j                  d      }|dk(  rt        |j                  |||            S t        |j                  |||            S |dk(  rRt        t        | j                  d      xs | j                  d            |      }	t        |j                  |	            S |dk(  rt        | j                  d      xs | j                  d            D 
cg c]  }
t        |
|       }}
|st	        d      S |dk(  rt        |j!                  |            S t        |j#                  |            S t	        d|       S c c}
w # t$        $ r}t'        |      cY d}~S d}~ww xY w)zEUnified handler for saved tracks + saved albums (formerly two tools).kindrd   >   albumsr   z#kind must be one of: tracks, albumsrC   r@   r   rU   rW   rm   r%   rn   r   rS   rQ   )rm   rS   rQ   saverT   rp   )rT   removeidsz)ids/items is required for action='remove')	track_ids)	album_idsz Unknown spotify_library action: N)r    r   r;   r<   r   r   r1   r-   r,   r   get_saved_tracksget_saved_albumsr   rB   save_library_itemsr   remove_saved_tracksremove_saved_albumsr   r$   )rw   rx   r   rC   	item_typery   rm   rS   rQ   rT   rA   r   r#   s                r   _handle_spotify_libraryr   '  s!   txx%2&,,.446D''?@@(#-v.446<<>F8+IF(V!$((7"3R@EC 2 7a89FXXh'Fx"6#:#:v^d#:#effv66U6Z`6abbV)(488F3C3XtxxPWGX*Y[deDv88d8CDDXEMdhhW\oNraeaiaijqarEstT'i8tCt!"MNNx"6#=#=#=#LMMv99C9HII<VHEFF u  ("3''(sV   A;H, H, 1AH, 4H, <H'H, H, >H, H, 'H, ,	I
5
I?I
I
r!   stringspotify_playbackz]Control Spotify playback, inspect the active playback state, or fetch recently played tracks.object)rK   rF   rR   r^   r_   r`   ra   rb   rf   rg   rj   )r!   enumarray)r!   rp   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))rC   rZ   rQ   rV   rT   rS   r[   rc   rh   rm   rk   rl   )r!   
propertiesrequired)r   r   
parametersspotify_deviceszHList Spotify Connect devices or transfer playback to a different device.r@   r   )rC   rZ   rR   spotify_queuez6Inspect the user's Spotify queue or add an item to it.r   r   )rC   r   rZ   spotify_searchzVSearch the Spotify catalog for tracks, albums, artists, playlists, shows, or episodes.)r   r   r!   rm   rS   rQ   r   r   spotify_playlistsz<List, inspect, create, update, and modify Spotify playlists.)r@   r   r   r   r   r   )rC   r   rQ   rm   rS   r   r   r   r   rT   r   r   spotify_albumsz-Fetch Spotify album metadata or album tracks.r   )rC   r   r   rQ   rm   rS   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   )r@   r   r   )r   rC   rm   rS   rQ   rT   r   rp   r   N)returnr   )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   z	List[str])rN   r   rC   r    r   zdict | None)rw   rM   r   r    ))__doc__
__future__r   typingr   r   hermes_cli.authr   plugins.spotify.clientr   r   r	   r
   r   r   r   tools.registryr   r   r   r   r$   r1   r>   rB   rO   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      s   G "  +   3K /1SU -	:,N(b("((,1(h(&(> " r'  2C  D&#($}=x("I.%y  GM  OW  FX  [a  cl  Zm  En  o%y1'8hi'8tu(9vw
 J! 0 ]'&*1EF&Y'

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

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