Ë
    âß²j?D  ã                  óî  — d Z ddlmZ ddlmZmZmZmZmZ ddl	m
Z
 ddlmZmZmZmZmZ ddlmZmZ eeeegef   Zd–d„Zd—d„Zd˜d	„Zd™d
„Zdšd›d„Zdœd„Zd„ Zd�džd„Zd„ ZdŸd d„Z dddœZ!d¡d„Z"dZ#d¢d„Z$d£d„Z%d„ Z&d¤d„Z'd¥d„Z(d¢d„Z) e ddd „ d!„ e$ e&d"d#«       e&d$d%«       e&d$d&«       e'd'd(e*«      d)„ d*„  e'd+d,d-„ «      e)d.œ«      Z+ e d/d0d1„ d2„ d3œ«      Z,d¢d4„Z- e d5d6d7„ e-d8œ«      Z.h d9£Z/d¥d:„Z0d¦d;„Z1 e d<d0d=„ d>„ d?„ d@„ dA„ dB„ dCœ«      Z2dD„ Z3dE„ Z4 e dFd6dG„ dH„ dIœe4¬J«      Z5d¥dK„Z6 e dLd0dM„ dN„ dO„ dPœ«      Z7d¥dQ„Z8dRdSiZ9dRdTiZ:dRdUiZ;dVe9dWœZ<dX„ Z=dY„ Z>dZ„ Z?d§d¨d]„Z@ e@dd^d e>dd_d`dadbdcdddedfdgdh«      i e=didjdk«      ¥e<dRdlie:dmdRdSidRdUigdnœe: e?do«       e?dp«       e?dq«      drœ¥«      ZA e@d/ds e>d0dt«      e9e;duœ«      ZB e@d5dvd e>d6dw«      i e=dxdi«      ¥«      ZC e@dydze9e<e9e:e:d{œ e=djd|«      ¥d}«      ZD e@d<d~d e>d0d6dd€d�d‚«      i e=dƒdj«      ¥e:e:d„œ¥ e=d[d\«      ¥e;e;e<e:e9d…œ¥«      ZE e@dFd†d e>d6d‡«      i e=dˆd‰dj«      ¥e:e:d„œ¥«      ZF e@dLdŠdSd‡d‹gdŒd�œ e>d0dŽd�«      e:e:e9e<e<e<d�œd‘«      ZGd’d“d”œZHd•„ ZIy)©a0  Native Spotify tools for Hermes (registered via plugins/spotify).

Each tool routes ``args["action"]`` through a dict dispatch table; every entry
has the signature ``(client, args, action) -> str`` and issues its Spotify Web
API call through ``client.request`` (auth refresh + error mapping live there).
é    )Úannotations)ÚAnyÚCallableÚDictÚListÚOptional)Úget_auth_status)Ú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© ó    ú:/home/ubuntu/.hermes/hermes-agent/plugins/spotify/tools.pyÚ_check_spotify_availabler      s4   € ðÜ”O IÓ.×2Ñ2°;Ó?Ó@Ð@øÜò Ùðús   ‚"% ¥	1°1c                ó’   — t        | t        «      rt        t        | «      «      S t        dt	        | «      j
                  › d| › �«      S )NzSpotify tool failed: z: )Ú
isinstancer   r   ÚstrÚtypeÚ__name__)Úexcs    r   Ú_spotify_tool_errorr!      s?   € Ü�#”|Ô$Üœ#˜c›(Ó#Ð#ÜÐ-¬d°3«i×.@Ñ.@Ð-AÀÀCÀ5ÐIÓJÐJr   c                ó    — | €t        |«      ‚| S ©N)r   )ÚvalueÚmessages     r   Ú	_requiredr&   "   s   € Ø€}Ü˜7Ó#Ð#Ø€Lr   c                óZ   — t        | xs d«      j                  «       }|st        |«      ‚|S )NÚ )r   Ústripr   )Úrawr%   r$   s      r   Ú	_nonblankr+   (   s+   € Ü�’	�r‹N× Ñ Ó"€EÙÜ˜7Ó#Ð#Ø€Lr   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   r)   Úlower)r*   ÚdefaultÚcleaneds      r   Ú_coerce_boolr8   /   sL   € Ü�#”tÔØˆ
Ü�#”sÔØ—)‘)“+×#Ñ#Ó%ˆØÐ0Ñ0ØØÐ1Ñ1ØØ€Nr   c                óÀ   — | €g S t        | t        «      r| n| g}|D �cg c]5  }t        |«      j                  «       sŒt        |«      j                  «       ‘Œ7 c}S c c}w r#   )r   Úlistr   r)   )r*   ÚitemsÚitems      r   Ú_as_listr=   ;   sJ   € Ø
€{Øˆ	Ü˜c¤4Ô(‰C¨s¨e€EØ*/ÖE $´3°t³9·?±?Õ3DŒC�‹I�O‰OÕÒEÐEùÒEs
   žA½Ac                óR   — t        dt        | j                  d«      xs d«      «      S )Nr   Úoffset)ÚmaxÚintr   ©Úargss    r   ú<lambda>rD   B   s    € ”s˜1œc $§(¡(¨8Ó"4Ò"9¸Ó:Ó;€ r   c                óŠ   — | j                  d«      }	 t        |«      }t        dt	        d|«      «      S # t        $ r |}Y Œ#w xY w)zUClamp ``limit`` to Spotify's 1..50 window; non-numeric input falls back to *default*.Úlimité   é2   )r   rA   r   r@   Úmin)rC   r6   r*   r$   s       r   Ú_limitrJ   E   sI   € à�x‰x˜Ó €CðÜ�C“ˆô ˆq”#�b˜%“.Ó!Ð!øô ò ØŠðús   “4 ´AÁAc                ó*   — t        d| dœ|¥d|i¥«      S )NT)ÚsuccessÚactionÚresult)r   )rM   rN   Úextras      r   rD   rD   O   s   € ¤k¸dÈfÑ2pÐX]Ð2pÐ_gÐioÑ2pÓ&q€ r   Nc                óB   ‡ ‡‡‡— dˆˆˆˆ fd„}d‰ › �x|_         |_        |S )aA  Build a tool handler that routes ``args['action']`` through *table*.

    The client is constructed outside the error boundary (auth failures propagate
    as exceptions, as they always have). *prepare* runs inside the boundary before
    the action lookup, so its validation errors surface even for unknown actions.
    c                ó@  •— t        | j                  d«      xs ‰«      j                  «       j                  «       }t	        «       }	 ‰� ‰| «      } ‰j                  |«      }|€t        d‰	› d|› �«      S  ||| |«      S # t        $ r}t        |«      cY d }~S d }~ww xY w)NrM   zUnknown z	 action: )r   r   r)   r5   r
   r   r   r!   )
rC   ÚkwrM   ÚclientÚhandlerr    r6   ÚprepareÚtableÚ	tool_names
         €€€€r   Úhandlez_dispatcher.<locals>.handleY   s�   ø€ Ü�T—X‘X˜hÓ'Ò2¨7Ó3×9Ñ9Ó;×AÑAÓCˆÜ“ˆð	,ØÐ"Ù˜t“}�Ø—i‘i Ó'ˆGØˆÜ! H¨Y¨K°yÀÀÐ"IÓJÐJÙ˜6 4¨Ó0Ð0øÜò 	,Ü& sÓ+Õ+ûð	,ús$   Á-A? Á5	A? Á?	BÂ
BÂBÂBÚ_handle_©rC   ÚdictÚreturnr   )r   Ú__qualname__)rW   r6   rV   rU   rX   s   ```` r   Ú_dispatcherr^   R   s*   û€ ÷,ð ,ð /7°y°kÐ,BÐB€F„O�fÔ)Ø€Mr   )Ú
is_playingz*Spotify is not currently playing anything.)Úhas_active_devicez-No active Spotify playback session was found.)Úget_currently_playingÚ	get_staterM   c                ó   —  | |j                  d«      ¬«      }t        |t        «      rL|j                  d«      r;t        |   \  }}ddd||dd|j                  dd	«      d
|j                  d
«      xs |i}t	        |«      S )NÚmarket)rd   ÚemptyrL   TrM   FÚstatus_codeéÌ   r%   )r   r   r[   Ú_EMPTY_PLAYBACKr   )ÚfetchrC   rM   ÚpayloadÚflagÚfallbacks         r   Ú_pb_readrm   q   s   € Ù˜4Ÿ8™8 HÓ-Ô.€GÜ�'œ4Ô  W§[¡[°Ô%9Ü(¨Ñ0‰ˆˆhØ˜d H¨f°d¸EÀ=ÐRY×R]ÑR]Ð^kÐmpÓRqØ˜gŸk™k¨)Ó4Ò@¸ðBˆä�wÓÐr   ))Úalbumzspotify:album:z/album/)Úplaylistzspotify:playlist:z
/playlist/)Úartistzspotify:artist:z/artist/c                óB  ‡— |j                  d«      }t        |t        «      r'|j                  «       D ��ci c]  \  }}|€Œ	||“Œ c}}nd }|j                  d«      r$t	        t        |j                  d«      «      d«      nd }d }|j                  d«      r?t        |j                  d«      «      Št        ˆfd„t        D «       d «      }	t        ‰|	«      }||||j                  d«      dœ}
t        || j                  dd	d
|j                  d
«      i|
¬«      «      S c c}}w )Nr?   ÚurisÚtrackÚcontext_uric              3  óV   •K  — | ]   \  }}}‰j                  |«      s|‰v sŒ|–— Œ" y ­wr#   )Ú
startswith)Ú.0ÚtÚprefixÚfragr*   s       €r   ú	<genexpr>z_pb_play.<locals>.<genexpr>…   s,   øè ø€ Òn¡? 1 f¨dÈÏÉÐW]ÔH^ÐbfÐjmÒbmœQÑnùs   ƒ)¢)Úposition_ms)rt   rr   r?   r|   ÚPUTz/me/player/playÚ	device_id)ÚparamsÚ	json_body)r   r   r[   r;   r   r=   r   ÚnextÚ_CONTEXT_TYPESr   Ú_okÚrequest)rS   rC   rM   r?   ÚkÚvÚpayload_offsetrr   rt   Úcontext_typeÚbodyr*   s              @r   Ú_pb_playrŠ   }   s  ø€ Ø�X‰X�hÓ€FÜKUÐV\Ô^bÔKc v§|¡|£~×G™t˜q !¸¹�a˜‘dÔGÐim€NØJNÏ(É(ÐSYÔJZÔ!¤(¨4¯8©8°FÓ+;Ó"<¸gÔFÐ`d€DØ€KØ‡x�x�ÔÜ�$—(‘(˜=Ó)Ó*ˆäÓn´nÔnÐptÓuˆÜ+¨C°Ó>ˆØ&°ÀÐ_c×_gÑ_gÐhuÓ_vÑw€DÜˆv�v—~‘~ eÐ->ÈÐUY×U]ÑU]Ð^iÓUjÐGkÐw{�~Ó|Ó}Ð}ùó Hs   ¶
DÁDc                óh   — t        || j                  ||i |¥d|j                  d«      i¥¬«      «      S )zRPlayer command whose only free argument is ``device_id`` (*extra* = fixed params).r~   ©r   )rƒ   r„   r   )rS   rC   rM   ÚmethodÚpathrO   s         r   Ú_pb_cmdr�   ‹   s8   € äˆv�v—~‘~ f¨dÐ;h¸eÐ;hÀ[ÐRV×RZÑRZÐ[fÓRgÑ;h�~ÓiÓjÐjr   c                ó   ‡ ‡— ˆ ˆfd„S )Nc                ó"   •— t        | ||‰‰«      S r#   )r�   )ÚcÚaÚactr�   rŽ   s      €€r   rD   z<lambda>.<locals>.<lambda>�   s   ø€ ¼ÀÀAÀsÈFÐTXÓ9Y€ r   r   )r�   rŽ   s   ``r   rD   rD   �   s   ù€ Ô'Y€ r   c                ó   ‡ ‡‡— ˆˆˆ fd„S )z?PUT *path* with ``param`` (required, converted) plus device_id.c                ór   •— t        | ||d‰fi ‰ ‰t        |j                  ‰«      ‰› d|› d�«      «      i¤ŽS )Nr}   z is required for action='ú')r�   r&   r   )r’   r“   r”   ÚconvertÚparamrŽ   s      €€€r   rD   z$_pb_required_param.<locals>.<lambda>•   sp   ø€ œW Q¨¨3°°tñ  UÀÁwÌyÐYZ×Y^ÑY^Ð_dÓYeÐjoÐipð  qJð  KNð  JOð  OPð  hQó  PRó  HSð  @Tñ  U€ r   r   )rŽ   r™   r˜   s   ```r   Ú_pb_required_paramrš   “   s   ú€ õ Uð  Ur   c                ó˜   — t        | j                  d«      xs d«      j                  «       j                  «       }|dvrt	        d«      ‚|S )NÚstater(   >   r3   rs   Úcontextz)state must be one of: track, context, off)r   r   r)   r5   r   )rC   rœ   s     r   Ú_pb_repeat_staterž   ˜   sF   € Ü�—‘˜Ó!Ò' RÓ(×.Ñ.Ó0×6Ñ6Ó8€EØÐ/Ñ/ÜÐFÓGÐGØ€Lr   c                óð   — |j                  d«      |j                  d«      }}|r|rt        d«      S t        |«      |�t        |«      nd |�t        |«      nd dœ}t	        | j                  dd|¬«      «      S )NÚafterÚbeforez'Provide only one of 'after' or 'before')rF   r    r¡   ÚGETz/me/player/recently-playedrŒ   )r   r   rJ   rA   r   r„   )rS   rC   rM   r    r¡   r   s         r   Ú_pb_recently_playedr£   Ÿ   s�   € Ø—H‘H˜WÓ% t§x¡x°Ó'9ˆ6€EÙ‘ÜÐCÓDÐDÜ˜d“|¸EÐ<M¬c°%¬jÐSWÐrxð  sEÔcfÐgmÔcnð  KOñ  P€FÜ�v—~‘~ eÐ-IÐRX�~ÓYÓZÐZr   Úspotify_playbackrb   c                ó0   — t        | j                  ||«      S r#   )rm   Úget_playback_state©r’   r“   r”   s      r   rD   rD   ¨   s   € ¤8¨A×,@Ñ,@À!ÀSÓ#I€ r   c                ó0   — t        | j                  ||«      S r#   )rm   ra   r§   s      r   rD   rD   ©   s   € ¬x¸×8OÑ8OÐQRÐTWÓ/X€ r   r}   z/me/player/pauseÚPOSTz/me/player/nextz/me/player/previousz/me/player/seekr|   c           
     ó6   — t        | ||ddt        |«      ¬«      S )Nr}   z/me/player/repeat©rœ   )r�   rž   r§   s      r   rD   rD   ¯   s   € ¤G¨A¨q°#°uÐ>QÔYiÐjkÓYlÔ$m€ r   c                ó‚   — t        | ||ddt        t        |j                  d«      «      «      j	                  «       ¬«      S )Nr}   z/me/player/shufflerœ   r«   )r�   r   r8   r   r5   r§   s      r   rD   rD   °   sG   € ¤W¨Q°°3¸Ð?SÔ[^Ô_kÐlm×lqÑlqÐryÓlzÓ_{Ó[|÷  \Cñ  \Có  \Eô  &F€ r   z/me/player/volumeÚvolume_percentc           	     ó@   — t        dt        dt        | «      «      «      S )Nr   éd   )r@   rI   rA   )r†   s    r   rD   rD   ±   s   € ÔVYÐZ[Ô]`ÐadÔfiÐjkÓflÓ]mÓVn€ r   )rb   ra   ÚplayÚpauser�   ÚpreviousÚseekÚ
set_repeatÚset_shuffleÚ
set_volumeÚrecently_playedÚspotify_devicesr:   c                ó8   — t        | j                  dd«      «      S )Nr¢   z/me/player/devices©r   r„   r§   s      r   rD   rD   ¹   s   € œk¨!¯)©)°EÐ;OÓ*PÓQ€ r   c                ó¨   — t        || j                  ddt        |j                  d«      d«      gt	        |j                  d«      «      dœ¬«      «      S )Nr}   z
/me/playerr~   z+device_id is required for action='transfer'r°   )Ú
device_idsr°   ©r€   )rƒ   r„   r+   r   r8   r§   s      r   rD   rD   º   sd   € ¤# c¨1¯9©9°U¸LÜ  §¡ {Ó!3Ð5bÓcÐdÔnzÐ{|÷  |Añ  |Að  BHó  |Ió  oJñU¨9ó ,ó #€ r   )r:   Útransferc                ó¶   — t        t        |j                  d«      xs d«      d «      }t        || j	                  dd||j                  d«      dœ¬«      |¬«      S )	NÚurir(   r©   ú/me/player/queuer~   )rÀ   r~   rŒ   )rÀ   )r   r   r   rƒ   r„   )rS   rC   rM   rÀ   s       r   Ú
_queue_addrÂ   À   s]   € Ü
¤ D§H¡H¨U£OÒ$9°rÓ :¸DÓ
A€CÜˆv�v—~‘~ fÐ.@ÐQTÐcg×ckÑckÐlwÓcxÑIy�~Ózð  ADô  Eð  Er   Úspotify_queuer   c                ó8   — t        | j                  dd«      «      S )Nr¢   rÁ   rº   r§   s      r   rD   rD   Æ   s   € œ[¨¯©°5Ð:LÓ)MÓN€ r   )r   Úadd>   Úshowrn   rs   rp   Úepisodero   Ú	audiobookc                óˆ  — 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                  «       t        v sŒ|j                  «       ‘Œ+ }}|st	        d«      S |dj                  |«      t        | d	«      t        | «      | j                  d
«      | j                  d«      dœ}	 t        |j                  dd|¬«      «      S c c}w # t        $ r}t        |«      cY d }~S d }~ww xY w)NÚqueryr(   zquery is requiredÚtypesr   rs   z[types must contain one or more of: album, artist, playlist, track, show, episode, audiobookú,é
   rd   Úinclude_external)Úqr   rF   r?   rd   rÎ   r¢   z/searchrŒ   )r
   r   r   r)   r   r=   r5   Ú_SEARCH_TYPESÚjoinrJ   Ú_offsetr   r„   r   r!   )	rC   rR   rS   rÊ   Ú	raw_typesr$   Úsearch_typesr   r    s	            r   Ú_handle_spotify_searchrÕ   Ë   s  € Ü‹_€FÜ�—‘˜Ó!Ò' RÓ(×.Ñ.Ó0€EÙÜÐ-Ó.Ð.Ü˜Ÿ™ 'Ó*ÒK¨d¯h©h°vÓ.>ÒKÀ7À)ÓL€IØ/8Ö[ e¸E¿K¹K»MÌ]Ò<Z�E—K‘K•MÐ[€LÐ[ÙÜÐwÓxÐxØ #§(¡(¨<Ó"8Ä6È$ÐPRÓCSÔ_fÐgkÓ_lØŸ™ Ó*ÀÇÁÐI[Ó@\ñ^€Fð(Ü˜6Ÿ>™>¨%°À6˜>ÓJÓKÐKùò \øô ò (Ü" 3Ó'Õ'ûð(ús*   Á:DÂDÄD# Ä#	EÄ,
D<Ä6EÄ<Ec                ó\   — dt        t        | j                  d«      xs d«      d«      › |› �S )Nz/playlists/Úplaylist_idr(   ro   ©r   r   r   )rC   Úsuffixs     r   rD   rD   Þ   s@   € ¨;Ô7KÌCÐPT×PXÑPXÐYfÓPgÒPmÐkmÓLnÐpzÓ7{Ð6|ð  ~Dð  }Eð  *F€ r   Úspotify_playlistsc           
     óf   — t        | j                  ddt        |«      t        |«      dœ¬«      «      S )Nr¢   ú/me/playlists©rF   r?   rŒ   )r   r„   rJ   rÒ   r§   s      r   rD   rD   â   s-   € œk¨!¯)©)°E¸?Ô]cÐdeÓ]fÔryÐz{Ór|ÑS}¨)Ó*~Ó€ r   c           
     óp   — t        | j                  dt        |«      d|j                  d«      i¬«      «      S )Nr¢   rd   rŒ   ©r   r„   Ú_playlist_pathr   r§   s      r   rD   rD   ã   s2   € œ[¨¯©°5¼.ÈÓ:KÐU]Ð_`×_dÑ_dÐemÓ_nÐTo¨Ó)pÓq€ r   c                óö   — t        | j                  ddt        |j                  d«      d«      t	        |j                  d«      «      t	        |j                  d«      «      |j                  d«      dœ¬	«      «      S )
Nr©   rÜ   Únamez$name is required for action='create'ÚpublicÚcollaborativeÚdescription©râ   rã   rä   rå   r½   )r   r„   r+   r   r8   r§   s      r   rD   rD   ä   sj   € ¤¨A¯I©I°f¸oÜ˜!Ÿ%™% ›-Ð)OÓPÔ\hÐij×inÑinÐowÓixÓ\yÜ% a§e¡e¨OÓ&<Ó=ÈaÏeÉeÐTaÓNbñZd¨Ió -eó !f€ r   c                ó¶   — t        | j                  dt        |d«      t        t	        |j                  d«      «      «      |j                  d«      dœ¬«      «      S )Nr©   ú/itemsrr   Úposition)rr   ré   r½   ©r   r„   rà   r   r=   r   r§   s      r   rD   rD   ç   sO   € ¤;¨q¯y©y¸ÄÐPQÐS[ÓA\Ü&¤x°·±°f³Ó'>Ó?ÈQÏUÉUÐS]ÓM^ñi`¨yó 0aó $b€ r   c                óà   — t        | j                  dt        |d«      t        t	        |j                  d«      «      «      D �cg c]  }d|i‘Œ c}|j                  d«      dœ¬«      «      S c c}w )NÚDELETErè   rr   rÀ   Úsnapshot_id)r;   rí   r½   rê   )r’   r“   r”   Úus       r   rD   rD   é   sd   € ¤k°!·)±)¸HÄnÐUVÐX`ÓFaÜ&<¼XÀaÇeÁeÈFÃmÓ=TÓ&UÖV �5˜!’*ÒVÐgh×glÑglÐmzÓg{ñn}°)ó 3~ó '€ ùÚVs   ÁA+c                óÐ   — t        | j                  dt        |«      |j                  d«      |j                  d«      |j                  d«      |j                  d«      dœ¬«      «      S )Nr}   râ   rã   rä   rå   ræ   r½   rß   r§   s      r   rD   rD   ë   sc   € ¬°A·I±I¸eÄ^ÐTUÓEVØ—‘�f“¨¯©¨x«È1Ï5É5ÐQ`ÓKaÐrs×rwÑrwð  yFó  sGñcH°Ió 5Ió )J€ r   )r:   r   ÚcreateÚ	add_itemsÚremove_itemsÚupdate_detailsc                óP   — t        | «      t        | «      | j                  d«      dœS )Nrd   )rF   r?   rd   )rJ   rÒ   r   rB   s    r   rD   rD   ò   s"   € ¤f¨T£l¼gÀd»mÐW[×W_ÑW_Ð`hÓWiÑj€ r   c           
     óŠ   — i | ¥ddt        t        | j                  d«      xs | j                  d«      xs d«      d«      › �i¥S )NÚ_pathz/albums/Úalbum_idÚidr(   rn   rØ   rB   s    r   rD   rD   ó   su   € ð  O ð  O w°(Ô;OÔPSÐTX×T\ÑT\Ð]gÓThò  UAÐlp×ltÑltÐuyÓlzò  UAð  Aó  QBð  DKó  <Lð  ;Mð  1Nñ  O€ r   Úspotify_albumsc           
     ód   — t        | j                  d|d   d|j                  d«      i¬«      «      S )Nr¢   rö   rd   rŒ   )r   r„   r   r§   s      r   rD   rD   ÷   s0   € œ[¨¯©°5¸!¸G¹*ÈhÐXY×X]ÑX]Ð^fÓXgÐMh¨Ó)iÓj€ r   c           	     óZ   — t        | j                  d|d   dz   t        |«      ¬«      «      S )Nr¢   rö   z/tracksrŒ   ©r   r„   Ú_page_paramsr§   s      r   rD   rD   ø   s*   € ¤¨A¯I©I°e¸Q¸w¹ZÈ)Ñ=SÔ\hÐijÓ\k¨IÓ,lÓ m€ r   )r   Útracks)rU   c                óð   ‡— | d   Št        | j                  d«      xs | j                  d«      «      D �cg c]  }t        |‰«      ‘Œ }}dj                  ˆfd„t	        |xs d d«      D «       «      S c c}w )NÚ
_item_typeÚidsr;   rÌ   c              3  ó.   •K  — | ]  }d ‰› d|› �–— Œ y­w)zspotify:ú:Nr   )rw   ÚiÚ	item_types     €r   r{   z#_lib_remove_uris.<locals>.<genexpr>  s   øè ø€ Ò|°1�h˜y˜k¨¨1¨#Ô.Ñ|ùs   ƒz)ids/items is required for action='remove')r=   r   r   rÑ   r&   )rC   r<   r  r  s      @r   Ú_lib_remove_urisr  þ   sn   ø€ Ø�\Ñ"€IÜ=EÀdÇhÁhÈuÃoÒFjÐY]×YaÑYaÐbiÓYjÓ=kÖ
l°TÔ  iÕ0Ð
l€CÐ
lØ�8‰8Ó|¼	À#Â+ÈÐOzÓ8{Ô|Ó|Ð|ùò ms   ¶A3Úspotify_libraryc           	     óZ   — t        | j                  dd|d   › �t        |«      ¬«      «      S )Nr¢   z/me/ÚkindrŒ   rü   r§   s      r   rD   rD     s,   € œk¨!¯)©)°E¸TÀ!ÀFÁ)ÀÐ;MÔVbÐcdÓVe¨)Ó*fÓg€ r   c                óÎ   — t        | j                  ddddj                  t        t	        |j                  d«      xs |j                  d«      «      |d   «      «      i¬«      «      S )Nr}   ú/me/libraryrr   rÌ   r;   r   rŒ   )r   r„   rÑ   r   r=   r   r§   s      r   rD   rD     s]   € œk¨!¯)©)°E¸=Ø�—‘Ô/´¸¿¹¸v»Ò9XÈ!Ï%É%ÐPWË.Ó0YÐ[\Ð]iÑ[jÓkÓlðRn¨)ó +oó p€ r   c           
     óR   — t        | j                  dddt        |«      i¬«      «      S )Nrì   r  rr   rŒ   )r   r„   r  r§   s      r   rD   rD     s'   € ¤¨A¯I©I°hÀÐW]Ô_oÐpqÓ_rÐVs¨IÓ,tÓ u€ r   )r:   ÚsaveÚremovec                ó¾   — t        | j                  d«      xs d«      j                  «       j                  «       }|dvrt	        d«      S t        i | ¥||d d dœ¥«      S )Nr	  r(   >   Úalbumsrþ   z#kind must be one of: tracks, albumséÿÿÿÿ)r	  r   )r   r   r)   r5   r   Ú_dispatch_library)rC   rR   r	  s      r   Ú_handle_spotify_libraryr    s_   € Üˆt�x‰x˜ÓÒ% 2Ó&×,Ñ,Ó.×4Ñ4Ó6€DØÐ'Ñ'ÜÐ?Ó@Ð@ÜÐL ÐL¨dÀ$ÀsÈÀ)ÒLÓMÐMr   r   ÚstringÚintegerÚbooleanÚarray)r   r;   c                 ó6   — t         j                  | t        «      S r#   )r[   ÚfromkeysÚCOMMON_STRING)Únamess    r   rD   rD     s   € ”t—}‘} U¬MÓ:€ r   c                 ó   — dt        | «      dœS )Nr  )r   Úenum©r:   )Úvaluess    r   rD   rD     s   €  ´4¸³<Ñ@€ r   c                ó   — d| dœS )Nr  )r   rå   r   )Útexts    r   rD   rD     s   € ˜y¸Ñ>€ r   râ   rå   c                ó(   — | |d|t        |«      dœdœS )NÚobject)r   Ú
propertiesÚrequired)râ   rå   Ú
parametersr  )râ   rå   r$  r%  s       r   Ú_schemar'     s4   € Ø¨ÈXÐeoô  ~Bð  CKó  ~Lñ  EMñ  Nð  Nr   z]Control Spotify playback, inspect the active playback state, or fetch recently played tracks.ra   r°   r±   r�   r²   r³   r´   rµ   r¶   r·   r~   rd   rt   r#  zRFor set_repeat use track/context/off. For set_shuffle use boolean-like true/false.)rå   ÚoneOfz.For recently_played: number of tracks (max 50)z:For recently_played: Unix ms cursor (after this timestamp)z;For recently_played: Unix ms cursor (before this timestamp))rr   r?   r|   rœ   r­   rF   r    r¡   zHList Spotify Connect devices or transfer playback to a different device.r¾   )rM   r~   r°   z6Inspect the user's Spotify queue or add an item to it.rÅ   rÀ   Úspotify_searchzVSearch the Spotify catalog for tracks, albums, artists, playlists, shows, or episodes.)rÊ   rË   r   rF   r?   rÎ   )rÊ   z<List, inspect, create, update, and modify Spotify playlists.rð   rñ   rò   ró   r×   rÝ   )rã   rä   rr   ré   rí   z-Fetch Spotify album metadata or album tracks.rþ   r÷   rø   z\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	  rM   rF   r?   rd   rr   r  r;   )r	  rM   )úplugins.spotify.clientÚSpotifyAPIError)r*  ÚSpotifyAuthRequiredError)r+  r,  c                óÌ   — t         j                  | «      }|€t        dt        ›d| ›�«      ‚dd l}ddlm}  |t        | g|¢­Ž  t        |j                  |d   «      |d   «      S )Nzmodule z has no attribute r   )Ú	warn_oncerG   )	Ú_PLUGIN_COMPAT_LAZYr   ÚAttributeErrorr   Ú	importlibÚhermes_cli.plugin_compatr.  ÚgetattrÚimport_module)râ   Útargetr1  r.  s       r   Ú__getattr__r6  K  se   € Ü ×$Ñ$ TÓ*€FØ€~Ü˜w¤x lÐ2DÀTÀHÐMÓNÐNÛÝ2ÙŒh˜Ð&˜vÓ&Ü�9×*Ñ*¨6°!©9Ó5°v¸a±yÓAÐAr   )r\   r   )r    r   r\   r   )r$   r   r%   r   r\   r   )r*   r   r%   r   r\   r   )F)r*   r   r6   r   r\   r   )r*   r   r\   z	List[str])é   )rC   r[   r6   rA   r\   rA   r#   )rW   r   r6   r   rV   zDict[str, _Handler]rU   z Optional[Callable[[dict], dict]])ri   zCallable[..., Any]rC   r[   rM   r   r\   r   )rS   r
   rC   r[   rM   r   r\   r   )rS   r
   rC   r[   rM   r   r�   r   rŽ   r   rO   r   r\   r   )rŽ   r   r™   r   r˜   zCallable[[Any], Any]r\   Ú_HandlerrZ   )r(   ))rM   )
râ   r   rå   r   r$  r[   r%  Útupler\   r[   )JÚ__doc__Ú
__future__r   Útypingr   r   r   r   r   Úhermes_cli.authr	   Úplugins.spotify.clientr
   r   r   r   r   Útools.registryr   r   r[   r   r8  r   r!   r&   r+   r8   r=   rÒ   rJ   rƒ   r^   rh   rm   r‚   rŠ   r�   Ú_pb_device_cmdrš   rž   r£   rA   Ú_handle_spotify_playbackÚ_handle_spotify_devicesrÂ   Ú_handle_spotify_queuerÐ   rÕ   rà   Ú_handle_spotify_playlistsrý   Ú_prepare_albumÚ_handle_spotify_albumsr  r  r  r  Ú_INTÚ_BOOLÚ
_STR_ARRAYÚ_strsÚ_enumÚ_idescr'  ÚSPOTIFY_PLAYBACK_SCHEMAÚSPOTIFY_DEVICES_SCHEMAÚSPOTIFY_QUEUE_SCHEMAÚSPOTIFY_SEARCH_SCHEMAÚSPOTIFY_PLAYLISTS_SCHEMAÚSPOTIFY_ALBUMS_SCHEMAÚSPOTIFY_LIBRARY_SCHEMAr/  r6  r   r   r   ú<module>rT     s
  ðñõ #ç 6Õ 6å +÷fõ fç 2à�] D¨#Ð.°Ð3Ñ4€óóKóóô	óFñ <€ô"ñ r€ôð6 ZØWñY€ó
 ð V€ó~ókñ
 [€óUó
ó[ñ 'Ð'9¸;ÙIÙXØÙ˜EÐ#5Ó6Ù˜6Ð#4Ó5Ù˜vÐ'<Ó=ÙÐ0°-ÀÓEÙmñ FÙ$Ð%8Ð:JÑLnÓoØ*ñIó Ð ñ" &Ð&7¸ÙQññBó Ð óEñ
 $ O°UÙNÐWañ=có dÐ ò Y€ó(ò& F€ñ (Ð(;¸VÙÙqñfñbññJñFó Ð ñ" k€ñ O€ñ %Ð%5°uÙjÙmñ?ð ôÐ ó}ñ  Ð 1°6Ùgñpáuñ	<ó Ð óNð ˜Ð"€Ø�	Ð€Ø	�Ð€Ø¨Ñ6€
ñ 	;€Ù@€Ù	>€ôNñ "Ð"4ð  7VØ‰e�KÐ!8¸&À'È6ÐS]Ð_eÐgsð  vCð  EQð  Sdó  eðXáˆK˜ =Ó1ðXà;EÐRXÐZbÐQcÐtxØqð  Eð  GOð  ~Pð  SYð  [dð  Reð  }fñ  gØ¡VÐ,\Ó%]ÙÐPÓQÑ]cð  ebó  ^còXó Ð ñ !Ð!2Ð4~Ù,1°&¸*Ó,EÐTaÐkpÑ!qósÐ á˜Ð0hÐksÑuzð  |Að  CHó  vIð  kgñ  MRð  SXð  Zeó  Mfð  kgó  hÐ ÙØÐnØ j¸-ÐRVÐbfñ  OÑjoÐpxð  {Mó  kNð  Oð  Q[óÐ ñ #Ð#6Ð8vØ‰e�F˜E 8¨[¸.ÐJZÓ[ðyqáˆM˜8Ó$ðyqà/3¸tòyqáGLÈVÐUbÓGcðyqð  e°ZÈTÐboòyqó rÐ ñ  Ð 0Ð2aØ!)©5°¸Ó+Að  !GÁUÈ:ÐW[Ð]eÓEfð  !GÐquð  BFò  !GóHÐ á Ð!2ð  5SØ¨°(Ð';ÐLiÑjÙ�F˜F HÓ-Ø˜T¨]ÀJÐWaÐlvñUð ó	Ð ð EØ VñÐ óBr   