
    i@                        S r SSKJr  SSKJrJrJrJrJr  SSK	J
r
  SSKJrJr  SrSrS	r " S
 S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rg)z>Utility classes to setup OAuth and link accounts to gallery-dl   )	Extractor   )textoauthutilconfig	exception)stdout_write)cachememcachezhttp://localhost:6414/z5https://mikf.github.io/gallery-dl/oauth-redirect.html)) Nc                   l    \ rS rSrSrSr\rS rS r	SS jr
S rS	 rSS
 jrS rS r  SS jrS rSrg)	OAuthBase   zBase class for OAuth Helpersr   c                 >    [         R                  " X5        S U l        g N)r   __init__clientselfmatchs     G/app/mltbenv/lib/python3.13/site-packages/gallery_dl/extractor/oauth.pyr   OAuthBase.__init__   s    4'    c                     [         R                  " SU R                  4SS5      U l        U R                  (       a1  [        [        L a#  U R
                  R                  S5        SU l        g g g )N	extractorr   Tzcache file is not writeableF)r   getcategoryr   r   logwarningr   s    r   _initOAuthBase._init   sN    ZZdmm <gtL
::%8+HH:;DJ ,:r   Nc                 V    [         R                  " SU R                  4U5      nUb  U$ U$ )Nr   )r   interpolatesubcategory)r   keydefaultvalues       r   oauth_configOAuthBase.oauth_config$   s/    ""K1A1A#BCH)u6w6r   c                    SSK n[        S5        UR                  UR                  UR                  5      nUR	                  UR
                  UR                  S5        UR                  U R                  SS5      U R                  SS5      45        UR                  S5        [        R                  (       a  UR                  S	5          UR                  5       S   U l         UR!                  5         Sn U R                  R#                  S
5      R%                  5       nUR'                  SS5      S   n[(        R*                  " UR-                  S5      S   5      $ ! UR                   a     Of = fM  ! [.         at  nUc  SnO*U(       d  SnSnOU R0                  R3                  SU5        SnU(       a  SUR4                  R6                   SU S3n[8        R:                  " U SU 35      eSnAff = f)z3Open local HTTP server and recv callback parameters    Nz+Waiting for response. (Cancel with Ctrl+c)
r   host	localhostporti  g      ?i    r   ?zFailed to receiver   zReceived emptyzResponse: %rzReceived invalidz (z: )z OAuth response)socketr
   AF_INETSOCK_STREAM
setsockopt
SOL_SOCKETSO_REUSEADDRbindr   listenr   WINDOWS
settimeoutacceptr   timeoutcloserecvdecodesplitr   parse_query	partition	Exceptionr    r!   	__class____name__r	   AbortExtraction)r   r5   serverdatapathexcmsgs          r   rB   OAuthBase.recv(   s   CDv~~v/A/AB&++V-@-@!DT[[5[[.0 	1a <<c"$mmoa0 		J;;##D)002D::c1%a(D##DNN3$7$:;; >> 	   	J|)&  6(3==112"SE;++se?3%,HII	Js,   	E 5A%E3 E.-E.3
G1=A/G,,G1c                     [        U5        U R                  R                  SUR                  5       -   5        U R                  R	                  5         g)z+Send 'msg' to the socket opened in 'recv()'s   HTTP/1.1 200 OK

N)r
   r   sendencoderA   r   rO   s     r   rR   OAuthBase.sendO   s8    S3cjjlBCr   c                    U S[         R                  " U5       3nU R                  SS5      =n(       a   SSKnUR	                  5       nU(       aU  UR                  U5      (       a?  [        USS5      =n(       a*  U R                  R                  SUR                  5       5        OU R                  R                  S5        [        S	U S
35        U=(       d    U R                  " 5       $ ! [
         a    Sn Nf = f)z4Open 'url' in browser amd return response parametersr3   browserTr.   NnamezOpening URL with %s:z%Please open this URL in your browser:


)r   build_queryr   
webbrowserr   rG   opengetattrr    info
capitalizer
   rB   )r   urlparamsrB   rW   r\   rX   s          r   r]   OAuthBase.openU   s    Qt''/01kk)T2272!$..* w||C((w55t54doo6GHHHMMABr#d^$!		!$$  s   C* *C98C9c                 ,    U R                  SU S35      $ )Nz"Remote server reported an error:

rY   )rR   rT   s     r   errorOAuthBase.errori   s    yy23%r:< 	<r   c                    U R                  S5      =(       d    UnU R                  S5      =(       d    Un[        R                  " Xg5      U l        U R                  R                  SXa:X  a  SOSU R                  U5        SU R                  0nU R                  X8S9R                  n	[        R                  " U	5      n	U	S   U R                  R                  l        U	S	   S
S.nU R                  XH5      n	U R                  XYS9R                  n	[        R                  " U	5      n	U	S	   n
U	S   nU R                  (       ah  U R                  U R                  R                  R                  4n[        R                   R#                  XU45        U R                  R                  S5        U R%                  U R'                  SX45      5        g)z)Perform the OAuth 1.0a authorization flowzapi-keyz
api-secretzUsing %s %s API key (%s)r)   customoauth_callback)rb   oauth_token_secretoauth_tokenread)rk   permszWriting tokens to cache)zaccess-tokenzaccess-token-secretN)r+   r   OAuth1Sessionsessionr    r_   r'   redirect_urirequestr   rE   authtoken_secretr]   r   consumer_key_token_cacheupdaterR   _generate_message)r   default_keydefault_secretrequest_token_urlauthorize_urlaccess_token_urlapi_key
api_secretrb   rL   tokenrs   r(   s                r   _oauth1_authorization_flow$OAuthBase._oauth1_authorization_flowm   s   
 ##I.=+&&|4F
**7?0#*#9ix&&	1
 #D$5$56||-|=BB%)-.B)C& "&m!4vFyy/ ||,|:??%]#01 ::##T\\%6%6%C%CDC%%c<+@AHHMM34 			$((3!
 	r   c                    U(       a  [        U5      OUnU=(       d    UnU R                  R                  SX:X  a  SOSU=(       d    U R                  U5        SU R                   S[        R
                  " S5       3nUSUU R                  UUS.nU R                  X^5      nXR                  S	5      :w  a(  U R                  S
U SUR                  S	5       S35        gSU;   a  U R                  U5      $ SUS   U R                  S.nU
(       a  [        R                  " X5      n
OSn
UUS'   UUS'   U R                  USUU
S9nSU;   a  U R                  U5      $ UU	   nU	R                  SS5      nU R                  (       aK  U(       aD  UR                   " U=(       d    S[        U5      -   U5        U R                  R                  SU5        U R                  U R#                  U4U45      5        g)z*Perform an OAuth2 authorization code grantzUsing %s %s client ID (%s)r)   rh   zgallery-dl__   code)	client_idresponse_typestaterp   durationscoper   z'state' mismatch: expected z, got .
Nre   authorization_code)
grant_typer   rp   r   client_secretPOST)methodrL   rr   -#zWriting '%s' to cache)strr    r_   r'   r   noncerp   r]   r   rR   re   r   HTTPBasicAuthrequest_jsonreplacer   rv   rw   )r   r   r   
default_idry   auth_url	token_urlr   r   r(   rr   r   instancer   auth_paramsrb   rL   r   
token_names                      r    _oauth2_authorization_code_grant*OAuthBase._oauth2_authorization_code_grant   s    '0C	NZ	%72#,#:i2$"2"2I	? d../qQ0@A '#"!..%"
 81 JJw''II3E7 ;#ZZ016 7f::f%% 1"6N --
 %%i?DD )D$1D!  f4d ! < d?::d##S	[[c*
 ::%LL;cC	N&:UCHHMM1:> 			$((ME8
 	r   c                   ^  [        U5      S:X  a  SOSu  p4pVSR                  S U 5       5      nSR                  U5      nSU SU S	U S	3n	T R                  US
   5      n
T R                  (       a  U
b  U
S:X  a	  XS-   -  n	U	$ U	SU S3-  n	U	SR                  U 4S jU 5       5      -  n	T R                  (       a  U	 ST R                   SUS
    S3n	U	 SU S3n	U	$ )Nr   )zThis value hasz
this valueisit)zThese values havezthese valuesarethemz and c              3   .   #    U  H  nS U S 3v   M     g7f)'N ).0ns     r   	<genexpr>.OAuthBase._generate_message.<locals>.<genexpr>   s     3UQqc8Us   rY   z
Your r2   rZ   r.   r   z- been cached and will automatically be used.
zPut z" into your configuration file as 
z and
c              3   J   >#    U  H  nS TR                    SU S3v   M     g7f)z'extractor..r   N)r'   )r   r   r   s     r   r   r      s.      !A d../q15s    #z
or set
'extractor.r   z' to "cache"z
to use r   )lenjoinr+   r   r'   )r   namesvalues_vh_va_is_itr(   valrO   opts   `          r   rw   OAuthBase._generate_message   s    5zQ 9@ 	# ll3U33iiuAcU$se40a)::3;#.IIIC 
 T#ABBC8== !!  C zz3**+1U1XJnFE3%s+C
r   )r   r   ro   r   )rl   	permanentrefresh_tokenTNN)rI   
__module____qualname____firstlineno____doc__r   REDIRECT_URI_LOCALHOSTrp   r   r#   r+   rB   rR   r]   re   r   r   rw   __static_attributes__r   r   r   r   r      sO    &H)L7%JN%(<(X 9DAECJr   r   c                   *    \ rS rSrSrSrSr\rS r	Sr
g)OAuthFlickr   flickrzoauth:flickr$zoauth:flickrc                 J    U R                  SSSSS5        [        [        5      $ )Nr   z3https://www.flickr.com/services/oauth/request_tokenz/https://www.flickr.com/services/oauth/authorizez2https://www.flickr.com/services/oauth/access_token)r   iterNOOPr"   s    r   itemsOAuthFlickr.items  s/     	'' A=@	
 Dzr   r   NrI   r   r   r   r'   patternexampleREDIRECT_URI_HTTPSrp   r   r   r   r   r   r   r      s    KGG%Lr   r   c                   &    \ rS rSrSrSrSrS rSrg)OAuthSmugmugi  smugmugzoauth:smugmug$zoauth:smugmugc                     SSK Jn  U R                  UR                  R                  UR                  R
                  SSS5        [        [        5      $ )Nr   )r   z;https://api.smugmug.com/services/oauth/1.0a/getRequestTokenz5https://api.smugmug.com/services/oauth/1.0a/authorizez:https://api.smugmug.com/services/oauth/1.0a/getAccessToken)r   r   r   
SmugmugAPIAPI_KEY
API_SECRETr   r   )r   r   s     r   r   OAuthSmugmug.items  sF    ''&&))ICH	
 Dzr   r   N	rI   r   r   r   r'   r   r   r   r   r   r   r   r   r     s    KGG
r   r   c                   &    \ rS rSrSrSrSrS rSrg)OAuthTumblri"  tumblrzoauth:tumblr$zoauth:tumblrc                     SSK Jn  U R                  UR                  R                  UR                  R
                  SSS5        [        [        5      $ )Nr   )r   z*https://www.tumblr.com/oauth/request_tokenz&https://www.tumblr.com/oauth/authorizez)https://www.tumblr.com/oauth/access_token)r   r   r   	TumblrAPIr   r   r   r   )r   r   s     r   r   OAuthTumblr.items'  sF    ''$$''847	
 Dzr   r   Nr   r   r   r   r   r   "  s    KGG
r   r   c                   *    \ rS rSrSrSrSr\rS r	Sr
g)OAuthDeviantarti7  
deviantartzoauth:deviantart$zoauth:deviantartc                     SSK Jn  U R                  U R                  S5      U R                  S5      UR                  R
                  UR                  R                  SSSUR                  S9  [        [        5      $ )	Nr   )r   	client-idclient-secretz+https://www.deviantart.com/oauth2/authorizez'https://www.deviantart.com/oauth2/tokenzbrowse user.manager   r   )
r   r   r   r+   DeviantartOAuthAPI	CLIENT_IDCLIENT_SECRET_refresh_token_cacher   r   )r   r   s     r   r   OAuthDeviantart.items=  sp     --k*o.))33))7795&11 	. 		
 Dzr   r   Nr   r   r   r   r   r   7  s    K!G G%Lr   r   c                   &    \ rS rSrSrSrSrS rSrg)OAuthRedditiM  redditzoauth:reddit$zoauth:redditc                    SSK Jn  UR                  R                  U R                  R
                  S'   U R                  U R                  S5      SUR                  R                  SSSSUR                  S	9  [        [        5      $ )
Nr   )r   
User-Agentr   r   z'https://www.reddit.com/api/v1/authorizez*https://www.reddit.com/api/v1/access_tokenzread historyr   )r   r   	RedditAPI
USER_AGENTro   headersr   r+   r   r   r   r   )r   r   s     r   r   OAuthReddit.itemsR  sy    -3-=-=-H-H\*--k*&&58 -- 	. 		
 Dzr   r   Nr   r   r   r   r   r   M  s    KGGr   r   c                   F    \ rS rSrSrSrSrS rS r\	" SSS	9S
 5       r
Srg)OAuthMastodonic  mastodonz&oauth:mastodon:(?:https?://)?([^/?#]+)zoauth:mastodon:mastodon.socialc                 B    [         R                  X5        US   U l        g )Nr   )r   r   r   r   s     r   r   OAuthMastodon.__init__h  s    4'ar   c                    SSK Jn  UR                  R                   H*  u  p#nU R                  UR                  S5      S   :X  d  M*    O   U R                  U R                  5      nU R                  US   US   US   US   SU R                   S3SU R                   S	3U R                  S
UR                  S9	  [        [        5      $ )Nr   )r   z://r   r   r   https://z/oauth/authorizez/oauth/tokenaccess_token)r   r(   r   )r   r   MastodonExtractor	instancesr   rF   	_registerr   _access_token_cacher   r   )r   r   r   rootapplications        r   r   OAuthMastodon.itemsl  s    $,$>$>$H$H A[}}u 5a 88 %I ..7K--$($(t}}o%56t}}o\2]].. 	. 
	
 Dzr   l    w r   )maxagekeyargc                    U R                   R                  SU5        SU S3nS[        R                  " S5      -   U R                  SS.nU R                  USUS	9nS
U;  d  SU;  a  [        R                  " SU S35      eUR                  S
5      US'   UR                  S5      US'   U R                   R                  SUS   5        U R                   R                  SUS   5        U$ )Nz Registering application for '%s'r   z/api/v1/appszgdl:r   rl   )client_nameredirect_urisscopesr   )r   rL   r   r   z%Failed to register new application: 'r   r   r   zclient-id:
%szclient-secret:
%s)	r    r_   r   r   rp   r   r	   rJ   pop)r   r   ra   rL   s       r   r   OAuthMastodon._register  s    8(C
,/!EKKN2!..

   V$ ?d"oT&A++7vQ?A A !HH[1[ $ 9_&[(9:*D,ABr   )r   N)rI   r   r   r   r'   r   r   r   r   r   r   r   r   r   r   r   r   c  s6    K6G.G!, +a( )r   r   c                   ,    \ rS rSrSrSrSrS rS rSr	g)	
OAuthPixivi  pixivzoauth:pixiv$zoauth:pixivc                    SSK Jn  SS KnSS Kn[        R
                  " S5      nUR                  UR                  5       5      R                  5       nUR                  U5      S S R                  5       R                  SS5      R                  SS	5      nS
nUSSS.nU R                  XxU R                  5      n	SnSS0n
U R                  SUR                  R                   5      U R                  SUR                  R"                  5      U	USSSS.nU R%                  USXS9nSU;   a$  ['        SU S35        US   S;   a  ['        S5        g US   nU R(                  (       aG  U R                  S5      nUR*                  R-                  X5        U R.                  R1                  S5        ['        U R3                  S U45      5        [5        [6        5      $ )!Nr   )r  r.       +r   /r   z&https://app-api.pixiv.net/web/v1/loginS256zpixiv-android)code_challengecode_challenge_methodr   z)https://oauth.secure.pixiv.net/auth/tokenr   z-PixivAndroidApp/5.0.234 (Android 11; Pixel 5)r   r   r   truez:https://app-api.pixiv.net/web/v1/users/auth/pixiv/callback)r   r   r   code_verifierr   include_policyrp   r   )r   r   rL   re   rY   )invalid_requestinvalid_grantz'code' expired, try again

r   usernamez Writing 'refresh-token' to cache)zrefresh-token)r   r  binasciihashlibr   generate_tokensha256rS   digest
b2a_base64rC   r   r]   _input_coder+   PixivAppAPIr   r   r   r
   r   r   rv   r    r_   rw   r   r   )r   r  r  r  r  r  r  ra   rb   r   r   rL   r   r  s                 r   r   OAuthPixiv.items  s   ++B/ 4 4 67>>@!,,R''#s"3GGC4E 	 7,%+%

 yyd&6&679I
 #//!2!2!<!<>"//!2!2!@!@B"+2$B
    ! < d?2dV2'G} DD<=_%::((4H&&--h>HHMM<=T++,>IJDzr   c                 ~    [        S5        U R                  S5      nUR                  S5      S   R                  5       $ )Na  1) Open your browser's Developer Tools (F12) and switch to the Network tab
2) Login
3) Select the last network monitor entry ('callback?state=...')
4) Copy its 'code' query parameter, paste it below, and press Enter

- This 'code' will expire 30 seconds after logging in.
- Copy-pasting more than just the 'code' value will work as well,
  like the entire URL or several query parameters.

zcode: =r   )r
   input
rpartitionstrip)r   r   s     r   r   OAuthPixiv._input_code  s<     
 
	 zz(#s#A&,,..r   r   N)
rI   r   r   r   r'   r   r   r   r   r   r   r   r   r
  r
    s    KGG2h/r   r
  N)r   commonr   r   r   r   r   r   r	   outputr
   r   r   r   r   r   r   r   r   r   r   r   r   r
  r   r   r   <module>r+     s    E  3 3 ! #1 L `	 `L) *9 $) *i ,) ,5I 5tF/ F/r   