File tree Expand file tree Collapse file tree 6 files changed +89
-6
lines changed
jupyterlab_leetcode/handlers Expand file tree Collapse file tree 6 files changed +89
-6
lines changed Original file line number Diff line number Diff line change 22
33from .base_handler import BaseHandler
44from .cookie_handler import GetCookieHandler
5+ from .leetcode_handler import LeetCodeProfileHandler
56
67
78def setup_handlers (web_app ):
89 host_pattern = ".*$"
910 base_url = web_app .settings ["base_url" ]
10- handlers : list [type [BaseHandler ]] = [GetCookieHandler ]
11+ handlers : list [type [BaseHandler ]] = [GetCookieHandler , LeetCodeProfileHandler ]
1112
1213 web_app .add_handlers (
1314 host_pattern ,
Original file line number Diff line number Diff line change 55
66import browser_cookie3
77import tornado
8+ from tornado .httpclient import AsyncHTTPClient
9+ from tornado .httputil import HTTPHeaders
810
911from .base_handler import BaseHandler
1012
@@ -60,10 +62,25 @@ def get(self):
6062 else 3600 * 24 * 14
6163 )
6264 self .set_cookie ("leetcode_browser" , browser , max_age = max_age )
65+ leetcode_ua = self .request .headers .get ("user-agent" )
6366 self .settings .update (
6467 leetcode_browser = browser ,
6568 leetcode_cookiejar = cj ,
66- leetcode_ua = self .request .headers .get ("user-agent" ),
69+ leetcode_headers = HTTPHeaders (
70+ {
71+ "Cookie" : "; " .join (f"{ c .name } ={ c .value } " for c in cj ),
72+ "Content-Type" : "application/json" ,
73+ "Origin" : "https://leetcode.com" ,
74+ "Referer" : "https://leetcode.com/" ,
75+ "X-CsrfToken" : (
76+ cookie_csrf .value
77+ if cookie_csrf and cookie_csrf .value
78+ else ""
79+ ),
80+ }
81+ ),
82+ leetcode_ua = leetcode_ua ,
6783 )
84+ AsyncHTTPClient .configure (None , defaults = dict (user_agent = leetcode_ua ))
6885
6986 self .finish (json .dumps (resp ))
Original file line number Diff line number Diff line change 1+ import json
2+
3+ import tornado
4+ from tornado .httpclient import AsyncHTTPClient , HTTPRequest
5+ from tornado .httputil import HTTPHeaders
6+
7+ from .base_handler import BaseHandler
8+
9+ LEETCODE_GRAPHQL_URL = "https://leetcode.com/graphql"
10+
11+
12+ class LeetCodeProfileHandler (BaseHandler ):
13+ route = r"leetcode/profile"
14+
15+ @tornado .web .authenticated
16+ async def get (self ):
17+ client = AsyncHTTPClient ()
18+ headers = HTTPHeaders (self .settings .get ("leetcode_headers" , {}))
19+ req = HTTPRequest (
20+ url = LEETCODE_GRAPHQL_URL ,
21+ method = "POST" ,
22+ headers = headers ,
23+ body = json .dumps (
24+ {
25+ "operationName" : "globalData" ,
26+ "variables" : {},
27+ "query" : "query globalData { userStatus { isSignedIn username realName avatar } }" ,
28+ }
29+ ),
30+ )
31+
32+ try :
33+ resp = await client .fetch (req )
34+ except Exception as e :
35+ self .log .error (f"Error fetching LeetCode profile: { e } " )
36+ self .set_status (500 )
37+ self .finish (json .dumps ({"message" : "Failed to fetch LeetCode profile" }))
38+ return
39+ else :
40+ self .finish (resp .body )
Original file line number Diff line number Diff line change 1- import React , { useState } from 'react' ;
1+ import React , { useEffect , useState } from 'react' ;
2+ import { getProfile } from '../services/leetcode' ;
23
34const LeetCode = ( ) => {
4- const [ _username , _setUsername ] = useState ( '' ) ;
5+ const [ username , setUsername ] = useState ( '' ) ;
56
6- // useEffect(() => {}, []);
7+ useEffect ( ( ) => {
8+ getProfile ( ) . then ( profile => {
9+ if ( ! profile || ! profile . isSignedIn ) {
10+ alert ( 'Please sign in to LeetCode.' ) ;
11+ return ;
12+ }
13+ setUsername ( profile . username ) ;
14+ } ) ;
15+ } , [ ] ) ;
716
817 return (
918 < div >
10- < p > Welcome username</ p >
19+ < p > Welcome { username } </ p >
1120 </ div >
1221 ) ;
1322} ;
Original file line number Diff line number Diff line change 1+ import { LeetCodeProfile } from '../types/leetcode' ;
2+ import { requestAPI } from './handler' ;
3+
4+ export async function getProfile ( ) : Promise < LeetCodeProfile | null > {
5+ return requestAPI < { data : { userStatus : LeetCodeProfile } } > (
6+ '/leetcode/profile'
7+ )
8+ . then ( d => d . data . userStatus )
9+ . catch ( ( ) => null ) ;
10+ }
Original file line number Diff line number Diff line change 1+ export type LeetCodeProfile = {
2+ avatar : string ;
3+ isSignedIn : boolean ;
4+ realName : string ;
5+ username : string ;
6+ } ;
You can’t perform that action at this time.
0 commit comments