+
    
.jY                         R t ^ RIt^ RIt^ RIt^ RIt^ RItRtRtR tR t	R t
R tR tRR	 ltRR
 ltRR ltR tRR ltR tR tR tR tR tR t]R8X  d    ]! R]! 4       4       ]! R]! R4      4       R# R# )a6  Spotify access for the glasses Spotify module.

Auth (client id/secret + tokens) lives in ~/.spotify_glasses/ (chmod 600, NOT
in this repo and NOT under /browse). Access token auto-refreshes via the
stored refresh token. No secrets in this file.

    from spotify_lib import get_current_track, search_and_play
Nz#/home/cameronsmith/.spotify_glasseszhttps://api.spotify.com/v1c                  V    \         P                  ! \        \        R ,           4      4      # )z/creds.jsonjsonloadopenD     8/data/cameron/agents_stuff/agents/glasses/spotify_lib.py_credsr      s    99T!m+,--r	   c                  V    \         P                  ! \        \        R ,           4      4      # )/tokens.jsonr   r   r	   r
   _tokensr      s    99T!n,-..r	   c            	      6   \        4       p \        P                  ! 4       V P                  R ^ 4      ^<,
          8  d
   V R,          # \        4       p\        P
                  ! VR,           RVR,           2P                  4       4      P                  4       p\        P                  ! RRRV 2/RR	R	V R	,          /R
7      pVP                  4        VP                  4       pVR,          V R&   \        \        P                  ! 4       4      VP                  RR4      ,           V R &   VP                  R	4      '       d   VR	,          V R	&   \        P                  ! V \        \        R,           R4      4       \         P"                  ! \        R,           R4       V R,          # )
expires_ataccess_token	client_id:client_secretz&https://accounts.spotify.com/api/tokenAuthorizationzBasic 
grant_typerefresh_token)headersdata
expires_ini  r   wi  )r   timegetr   base64	b64encodeencodedecoderequestspostraise_for_statusr   intdumpr   r   oschmod)tcauthrnts        r
   _access_tokenr.      sC   	Ayy{QUU<+b00  Aq~.a/0B/CDKKMNUUWD0 F4&/2O_a>PQ	A
 	
B>*An$))+&d)CCAlO	vvo0/IIaa.(#./HHQ'^r	   c                       R R\        4        2/# )r   zBearer )r.   r   r	   r
   _hr0   2   s    w}&7899r	   c                 .   \         P                  ! \        R,           \        4       ^R7      p V P                  ^8X  g!   V P
                  P                  4       '       g   R# V P                  4        V P                  4       pVP                  R4      ;'       g    / pV'       g   R# VP                  R4      ;'       g    / P                  R. 4      pRVP                  R4      RR	P                  R
 VP                  R. 4       4       4      RVP                  R4      ;'       g    / P                  R4      RV'       d   VR,          R,          MRRVP                  R4      ;'       g    ^ RVP                  R4      ;'       g    ^ RVP                  RR4      /# )z*Now playing, or None if nothing's playing.z/me/player/currently-playingr   timeoutNitemalbumimagesnameartist, c              3   2   "   T F  qR ,          x  K  	  R# 5ir7   Nr   .0as   & r
   	<genexpr>$get_current_track.<locals>.<genexpr>C   s     G/F!fII/F   artistsart_urlurlprogress_msduration_ms
is_playingF)
r"   r   APIr0   status_codetextstripr$   r   join)r,   jr4   imgss       r
   get_current_trackrP   6   s4   S9924QRSA}}166<<>>	A55=BDHHW##((26D $))Gtxx	2/FGG$((7#))r..v6d48E?quu]+00qtxx.33!aeeL%0 r	   c           
      t   \         P                  ! \        R ,           \        4       RV RRRV/^R7      pVP	                  4        VP                  4       P                  R/ 4      P                  R. 4      pV'       g   R# V^ ,          pR	VR	,          R
VR
,          RRP                  R VR,           4       4      /# )/searchqtypetracklimitr   paramsr3   tracksitemsNurir7   r8   r9   c              3   2   "   T F  qR ,          x  K  	  R# 5ir;   r   r<   s   & r
   r?   search.<locals>.<genexpr>S   s     CdWcRSfIIWcrA   rB   r"   r   rI   r0   r$   r   rM   )queryrV   r,   rZ   r)   s   &&   r
   searchr`   L   s    S9_bdCPWY`bg;hrstAFFHLL2&**7B7EaA1U8VQvY$))CdWXYbWcCd:deer	   c                   \         P                  ! \        R,           \        4       RV RRRV/^R7      pVP	                  4        VP                  4       P                  R/ 4      P                  R. 4       Uu. uFF  pR	VR	,          R
RP                  R VR,           4       4      RVR,          R	,          RVR,          /NKH  	  up# u upi )z.Top track matches from Spotify's live catalog.rR   rS   rT   rU   rV   rW   rY   rZ   r7   r8   r9   c              3   2   "   T F  qR ,          x  K  	  R# 5ir;   r   r<   s   & r
   r?    search_tracks.<locals>.<genexpr>Z   s     3T|!fII|rA   rB   r5   r[   r^   )r_   rV   r,   r)   s   &&  r
   search_tracksrd   V   s    S9_bdCPWY`bg;hrstA VVX\\(B/33GR@B@ QvY$))3Tq|3T*Taj(%5;@B B Bs   6ACc                  a \         P                  ! \        R,           \        4       RV RRR^
/^R7      pVP	                  4        V P                  4       P                  4       oVP                  4       P                  R/ 4      P                  R. 4       Uu. uFg  p\        ;QJ d/    V3R	 lVP                  R
. 4       4       F  '       g   K   RM$	  RM ! V3R	 lVP                  R
. 4       4       4      '       g   Ke  VNKi  	  ppVP                  R RR7       \        4       . reV F  pVR,          P                  4       P                  4       pWu9   d   K0  VP                  V4       VP                  RVR,          RVR,          RVP                  R4      RVP                  R4      RVR
,          ^ ,          R,          /4       K  	  VRV # u upi )u   An artist's albums/singles NEWEST FIRST, from Spotify's live catalog —
so 'newest album' is always current, not guessed. Uses album SEARCH because
the /artists/{id}/albums endpoint is restricted for newer dev apps.rR   rS   rT   r5   rV   rW   albumsrZ   c              3      <"   T F]  pSVR ,          P                  4       P                  4       8H  ;'       g)    SVR ,          P                  4       P                  4       9   x  K_  	  R# 5ir;   )rL   lower)r=   arnls   & r
   r?    artist_albums.<locals>.<genexpr>g   sU     wbv\^2F))+1133WWrRZ=M=M=O=U=U=W7WWbvs
   3A(1A(rB   TFc                 8    V P                  R 4      ;'       g    R# )release_date )r   )r>   s   &r
   <lambda>artist_albums.<locals>.<lambda>h   s    AEE.177R7r	   )keyreverser7   idrm   
album_typer8   N)r"   r   rI   r0   r$   rL   rh   r   anysortsetaddappend)	r7   rV   r,   r>   rowsseenoutkrj   s	   &&      @r
   artist_albumsr~   _   s    	S9_bdCvwX_ac;dnopA				Bvvx||Hb155grB yB!swbcbgbghqsubvwssswbcbgbghqsubvww ABD yII7IFr#fIOO##%9

FAfItQtWnaeeNF[AEE,/1Y<?6;RT 	U  v;ys   G%$G+G<Gc                    \         P                  ! \         R V  R2\        4       R^2RR/^R7      pVP	                  4        VP                  4       P                  R. 4       Uu. uF  pRVR,          RVR,          /NK  	  up# u upi )	z/albums/z/tracksrV   marketUSrW   rZ   r7   r[   )r"   r   rI   r0   r$   r   )album_idr,   r)   s   &  r
   album_tracksr   t   s{    uHXJg6$b(D91	FA:;&&(,,wPR:ST:SQVQvYqx0:STTTs   #Bc                     \         P                  ! \        R ,           \        4       V '       d   RV ./MR^R7      pVP                  # )/me/player/playurisN)r   r   r3   r"   putrI   r0   rJ   )r[   r,   s   & r
   playr   {   s5    S,,bdUX6C5/^bmnoA==r	   c                 |    \        V 4      pV'       g   R RRRV ,           /# \        VR,          4      pR VR9   RVRV/# )okFerrorzno results for r[   rU   code)         )r`   r   )r_   r)   r   s   &  r
   search_and_playr      sH    uAeW&7%&?@@%>D$/)7AvtDDr	   c                     \        V 4      # N)r   )r[   s   &r
   play_urir      s    9r	   c                  n    \         P                  ! \        R ,           \        4       ^R7      P                  # )z/me/player/pauser2   r   r   r	   r
   pauser      s#    <<00"$JVVVr	   c                  n    \         P                  ! \        R ,           \        4       ^R7      P                  # )r   r2   r   r   r	   r
   resumer      s#    <<//qIUUUr	   c                  |    \        4       p V '       d"   V P                  R 4      '       d   \        4       # \        4       # )rG   )rP   r   r   r   )trs    r
   toggle_playbackr      s)    		Bbff\2257AAr	   c                  n    \         P                  ! \        R ,           \        4       ^R7      P                  # )z/me/player/nextr2   )r"   r#   rI   r0   rJ   r   r	   r
   
next_trackr      s#    ==00"$JVVVr	   __main__zcurrent:zsearch 'bohemian rhapsody':zbohemian rhapsody)   )   )   r   )__doc__r   r   r'   r   r"   r   rI   r   r   r.   r0   rP   r`   rd   r~   r   r   r   r   r   r   r   r   __name__printr   r	   r
   <module>r      s      	  )"./,:,fB*U
EWVB
W z	*')*	
'0C)DE r	   