@@ -360,31 +360,25 @@ plugin.getSubmission = function(submission, cb) {
360
360
361
361
plugin . starProblem = function ( problem , starred , cb ) {
362
362
log . debug ( 'running leetcode.starProblem' ) ;
363
- const opts = plugin . makeOpts ( ) ;
363
+ const user = session . getUser ( ) ;
364
+ const operationName = starred ? 'addQuestionToFavorite' : 'removeQuestionFromFavorite' ;
365
+ const opts = plugin . makeOpts ( config . sys . urls . graphql ) ;
364
366
opts . headers . Origin = config . sys . urls . base ;
365
367
opts . headers . Referer = problem . link ;
366
368
367
- const user = session . getUser ( ) ;
368
- if ( starred ) {
369
- opts . url = config . sys . urls . favorites ;
370
- opts . method = 'POST' ;
371
- opts . json = true ;
372
- opts . body = {
373
- favorite_id_hash : user . hash ,
374
- question_id : problem . id
375
- } ;
376
- } else {
377
- opts . url = config . sys . urls . favorite_delete
378
- . replace ( '$hash' , user . hash )
379
- . replace ( '$id' , problem . id ) ;
380
- opts . method = 'DELETE' ;
381
- }
369
+ opts . json = true ;
370
+ opts . body = {
371
+ query : `mutation ${ operationName } ($favoriteIdHash: String!, $questionId: String!) {\n ${ operationName } (favoriteIdHash: $favoriteIdHash, questionId: $questionId) {\n ok\n error\n favoriteIdHash\n questionId\n __typename\n }\n}\n` ,
372
+ variables : { favoriteIdHash : user . hash , questionId : '' + problem . id } ,
373
+ operationName : operationName
374
+ } ;
382
375
383
- request ( opts , function ( e , resp , body ) {
384
- e = plugin . checkError ( e , resp , 204 ) ;
376
+ const spin = h . spin ( starred ? 'star' : 'unstar' + 'problem' ) ;
377
+ request . post ( opts , function ( e , resp , body ) {
378
+ spin . stop ( ) ;
379
+ e = plugin . checkError ( e , resp , 200 ) ;
385
380
if ( e ) return cb ( e ) ;
386
-
387
- cb ( null , starred ) ;
381
+ return cb ( null , starred ) ;
388
382
} ) ;
389
383
} ;
390
384
@@ -543,14 +537,13 @@ function parseCookie(cookie, body, cb) {
543
537
const isCN = config . app === 'leetcode.cn' ;
544
538
const SessionPattern = / L E E T C O D E _ S E S S I O N = ( .+ ?) ( ; | $ ) / ;
545
539
let csrfPattern ;
546
- // leetcode-cn.com Cookie is not the same as leetcode.com in third parties
547
540
if ( isCN ) {
548
541
csrfPattern = / n a m e = " c s r f m i d d l e w a r e t o k e n " v a l u e = " ( .* ?) " / ;
549
542
} else {
550
543
csrfPattern = / c s r f t o k e n = ( .+ ?) ( ; | $ ) / ;
551
544
}
552
- const reSessionResult = SessionPattern . exec ( cookie ) ;
553
545
const reCsrfResult = csrfPattern . exec ( isCN ? body : cookie ) ;
546
+ const reSessionResult = SessionPattern . exec ( cookie ) ;
554
547
if ( reSessionResult === null || reCsrfResult === null ) {
555
548
return cb ( 'invalid cookie?' ) ;
556
549
}
@@ -588,9 +581,18 @@ plugin.githubLogin = function(user, cb) {
588
581
const _request = request . defaults ( { jar : true } ) ;
589
582
_request ( urls . github_login_request , function ( e , resp , body ) {
590
583
const authenticityToken = body . match ( / n a m e = " a u t h e n t i c i t y _ t o k e n " v a l u e = " ( .* ?) " / ) ;
591
- if ( authenticityToken === null ) {
592
- return cb ( 'Get GitHub token failed' ) ;
584
+ let gaId = body . match ( / n a m e = " g a _ i d " v a l u e = " ( .* ?) " / ) ;
585
+ if ( ! gaId ) {
586
+ gaId = '' ;
587
+ }
588
+ let requiredField = body . match ( / n a m e = " r e q u i r e d _ f i e l d _ ( .* ?) " / ) ;
589
+ const timestamp = body . match ( / n a m e = " t i m e s t a m p " v a l u e = " ( .* ?) " / ) ;
590
+ const timestampSecret = body . match ( / n a m e = " t i m e s t a m p _ s e c r e t " v a l u e = " ( .* ?) " / ) ;
591
+
592
+ if ( ! ( authenticityToken && timestamp && timestampSecret && requiredField ) ) {
593
+ return cb ( 'Get GitHub payload failed' ) ;
593
594
}
595
+ requiredField = 'required_field_' + requiredField [ 1 ] ;
594
596
const options = {
595
597
url : urls . github_session_request ,
596
598
method : 'POST' ,
@@ -599,11 +601,17 @@ plugin.githubLogin = function(user, cb) {
599
601
} ,
600
602
followAllRedirects : true ,
601
603
form : {
602
- 'login' : user . login ,
603
- 'password' : user . pass ,
604
- 'authenticity_token' : authenticityToken [ 1 ] ,
605
- 'utf8' : encodeURIComponent ( '✓' ) ,
606
- 'commit' : encodeURIComponent ( 'Sign in' )
604
+ 'login' : user . login ,
605
+ 'password' : user . pass ,
606
+ 'authenticity_token' : authenticityToken [ 1 ] ,
607
+ 'commit' : encodeURIComponent ( 'Sign in' ) ,
608
+ 'ga_id' : gaId ,
609
+ 'webauthn-support' : 'supported' ,
610
+ 'webauthn-iuvpaa-support' : 'unsupported' ,
611
+ 'return_to' : '' ,
612
+ 'requiredField' : '' ,
613
+ 'timestamp' : timestamp [ 1 ] ,
614
+ 'timestamp_secret' : timestampSecret [ 1 ] ,
607
615
} ,
608
616
} ;
609
617
_request ( options , function ( e , resp , body ) {
@@ -664,9 +672,12 @@ plugin.linkedinLogin = function(user, cb) {
664
672
if ( resp . statusCode !== 200 ) {
665
673
return cb ( 'Get LinkedIn session failed' ) ;
666
674
}
667
- const authenticityToken = body . match ( / i n p u t n a m e = " l o g i n C s r f P a r a m " v a l u e = " ( .* ) " / ) ;
668
- if ( authenticityToken === null ) {
669
- return cb ( 'Get LinkedIn token failed' ) ;
675
+ const csrfToken = body . match ( / i n p u t t y p e = " h i d d e n " n a m e = " c s r f T o k e n " v a l u e = " ( .* ?) " / ) ;
676
+ const loginCsrfToken = body . match ( / i n p u t t y p e = " h i d d e n " n a m e = " l o g i n C s r f P a r a m " v a l u e = " ( .* ?) " / ) ;
677
+ const sIdString = body . match ( / i n p u t t y p e = " h i d d e n " n a m e = " s I d S t r i n g " v a l u e = " ( .* ?) " / ) ;
678
+ const pageInstance = body . match ( / i n p u t t y p e = " h i d d e n " n a m e = " p a g e I n s t a n c e " v a l u e = " ( .* ?) " / ) ;
679
+ if ( ! ( csrfToken && loginCsrfToken && sIdString && pageInstance ) ) {
680
+ return cb ( 'Get LinkedIn payload failed' ) ;
670
681
}
671
682
const options = {
672
683
url : urls . linkedin_session_request ,
@@ -676,10 +687,22 @@ plugin.linkedinLogin = function(user, cb) {
676
687
} ,
677
688
followAllRedirects : true ,
678
689
form : {
679
- 'session_key' : user . login ,
680
- 'session_password' : user . pass ,
681
- 'loginCsrfParam' : authenticityToken [ 1 ] ,
682
- 'trk' : 'guest_homepage-basic_sign-in-submit'
690
+ 'csrfToken' : csrfToken [ 1 ] ,
691
+ 'session_key' : user . login ,
692
+ 'ac' : 2 ,
693
+ 'sIdString' : sIdString [ 1 ] ,
694
+ 'parentPageKey' : 'd_checkpoint_lg_consumerLogin' ,
695
+ 'pageInstance' : pageInstance [ 1 ] ,
696
+ 'trk' : 'public_profile_nav-header-signin' ,
697
+ 'authUUID' : '' ,
698
+ 'session_redirect' : 'https://www.linkedin.com/feed/' ,
699
+ 'loginCsrfParam' : loginCsrfToken [ 1 ] ,
700
+ 'fp_data' : 'default' ,
701
+ '_d' : 'd' ,
702
+ 'showGoogleOneTapLogin' : true ,
703
+ 'controlId' : 'd_checkpoint_lg_consumerLogin-login_submit_button' ,
704
+ 'session_password' : user . pass ,
705
+ 'loginFlow' : 'REMEMBER_ME_OPTIN'
683
706
} ,
684
707
} ;
685
708
_request ( options , function ( e , resp , body ) {
0 commit comments