@@ -333,7 +333,7 @@ plugin.getSubmissions = function(problem, cb) {
333
333
334
334
// FIXME: this only return the 1st 20 submissions, we should get next if necessary.
335
335
const submissions = JSON . parse ( body ) . submissions_dump ;
336
- for ( let submission of submissions )
336
+ for ( const submission of submissions )
337
337
submission . id = _ . last ( _ . compact ( submission . url . split ( '/' ) ) ) ;
338
338
339
339
return cb ( null , submissions ) ;
@@ -471,8 +471,8 @@ plugin.deleteSession = function(session, cb) {
471
471
} ;
472
472
473
473
plugin . signin = function ( user , cb ) {
474
- log . debug ( 'running leetcode.signin' ) ;
475
- const spin = h . spin ( 'Signing in leetcode.com' ) ;
474
+ const isCN = config . app === ' leetcode.cn' ;
475
+ const spin = isCN ? h . spin ( 'Signing in leetcode-cn.com' ) : h . spin ( 'Signing in leetcode.com' ) ;
476
476
request ( config . sys . urls . login , function ( e , resp , body ) {
477
477
spin . stop ( ) ;
478
478
e = plugin . checkError ( e , resp , 200 ) ;
@@ -538,11 +538,18 @@ plugin.login = function(user, cb) {
538
538
} ) ;
539
539
} ;
540
540
541
- function parseCookie ( cookie , cb ) {
541
+ function parseCookie ( cookie , body , cb ) {
542
+ const isCN = config . app === 'leetcode.cn' ;
542
543
const SessionPattern = / L E E T C O D E _ S E S S I O N = ( .+ ?) ( ; | $ ) / ;
543
- const csrfPattern = / c s r f t o k e n = ( .+ ?) ( ; | $ ) / ;
544
+ let csrfPattern ;
545
+ // leetcode-cn.com Cookie is not the same as leetcode.com in third parties
546
+ if ( isCN ) {
547
+ 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 = " ( .* ?) " / ;
548
+ } else {
549
+ csrfPattern = / c s r f t o k e n = ( .+ ?) ( ; | $ ) / ;
550
+ }
544
551
const reSessionResult = SessionPattern . exec ( cookie ) ;
545
- const reCsrfResult = csrfPattern . exec ( cookie ) ;
552
+ const reCsrfResult = csrfPattern . exec ( isCN ? body : cookie ) ;
546
553
if ( reSessionResult === null || reCsrfResult === null ) {
547
554
return cb ( 'invalid cookie?' ) ;
548
555
}
@@ -552,11 +559,18 @@ function parseCookie(cookie, cb) {
552
559
} ;
553
560
}
554
561
555
- function saveAndGetUser ( user , cb , cookieData ) {
556
- user . sessionId = cookieData . sessionId ;
557
- user . sessionCSRF = cookieData . sessionCSRF ;
558
- session . saveUser ( user ) ;
559
- plugin . getUser ( user , cb ) ;
562
+ function requestLeetcodeAndSave ( request , leetcodeUrl , user , cb ) {
563
+ request . get ( { url : leetcodeUrl } , function ( e , resp , body ) {
564
+ const redirectUri = resp . request . uri . href ;
565
+ if ( redirectUri !== config . sys . urls . leetcode_redirect ) {
566
+ return cb ( 'Login failed. Please make sure the credential is correct.' ) ;
567
+ }
568
+ const cookieData = parseCookie ( resp . request . headers . cookie , body , cb ) ;
569
+ user . sessionId = cookieData . sessionId ;
570
+ user . sessionCSRF = cookieData . sessionCSRF ;
571
+ session . saveUser ( user ) ;
572
+ plugin . getUser ( user , cb ) ;
573
+ } ) ;
560
574
}
561
575
562
576
plugin . cookieLogin = function ( user , cb ) {
@@ -568,15 +582,16 @@ plugin.cookieLogin = function(user, cb) {
568
582
} ;
569
583
570
584
plugin . githubLogin = function ( user , cb ) {
571
- const leetcodeUrl = config . sys . urls . github_login ;
585
+ const urls = config . sys . urls ;
586
+ const leetcodeUrl = urls . github_login ;
572
587
const _request = request . defaults ( { jar : true } ) ;
573
- _request ( 'https://github.com/login' , function ( e , resp , body ) {
588
+ _request ( urls . github_login_request , function ( e , resp , body ) {
574
589
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 = " ( .* ?) " / ) ;
575
590
if ( authenticityToken === null ) {
576
591
return cb ( 'Get GitHub token failed' ) ;
577
592
}
578
593
const options = {
579
- url : 'https://github.com/session' ,
594
+ url : urls . github_session_request ,
580
595
method : 'POST' ,
581
596
headers : {
582
597
'Content-Type' : 'application/x-www-form-urlencoded' ,
@@ -594,27 +609,48 @@ plugin.githubLogin = function(user, cb) {
594
609
if ( resp . statusCode !== 200 ) {
595
610
return cb ( 'GitHub login failed' ) ;
596
611
}
597
- _request . get ( { url : leetcodeUrl } , function ( e , resp , body ) {
598
- const redirectUri = resp . request . uri . href ;
599
- if ( redirectUri !== 'https://leetcode.com/' ) {
600
- return cb ( 'GitHub login failed or GitHub did not link to LeetCode' ) ;
612
+ if ( resp . request . uri . href !== urls . github_tf_redirect ) {
613
+ return requestLeetcodeAndSave ( _request , leetcodeUrl , user , cb ) ;
614
+ }
615
+ // read two-factor code must be sync.
616
+ const twoFactorcode = require ( 'prompt-sync' ) ( ) ( 'Please enter your two-factor code: ' ) ;
617
+ const authenticityTokenTwoFactor = 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 = " ( .* ?) " / ) ;
618
+ if ( authenticityTokenTwoFactor === null ) {
619
+ return cb ( 'Get GitHub two-factor token failed' ) ;
620
+ }
621
+ const optionsTwoFactor = {
622
+ url : urls . github_tf_session_request ,
623
+ method : 'POST' ,
624
+ headers : {
625
+ 'Content-Type' : 'application/x-www-form-urlencoded' ,
626
+ } ,
627
+ followAllRedirects : true ,
628
+ form : {
629
+ 'otp' : twoFactorcode ,
630
+ 'authenticity_token' : authenticityTokenTwoFactor [ 1 ] ,
631
+ 'utf8' : encodeURIComponent ( '✓' ) ,
632
+ } ,
633
+ } ;
634
+ _request ( optionsTwoFactor , function ( e , resp , body ) {
635
+ if ( resp . request . uri . href === urls . github_tf_session_request ) {
636
+ return cb ( 'Invalid two-factor code please check' ) ;
601
637
}
602
- const cookieData = parseCookie ( resp . request . headers . cookie , cb ) ;
603
- saveAndGetUser ( user , cb , cookieData ) ;
638
+ requestLeetcodeAndSave ( _request , leetcodeUrl , user , cb ) ;
604
639
} ) ;
605
640
} ) ;
606
641
} ) ;
607
642
} ;
608
643
609
644
plugin . linkedinLogin = function ( user , cb ) {
610
- const leetcodeUrl = config . sys . urls . linkedin_login ;
645
+ const urls = config . sys . urls ;
646
+ const leetcodeUrl = urls . linkedin_login ;
611
647
const _request = request . defaults ( {
612
648
jar : true ,
613
649
headers : {
614
650
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
615
651
}
616
652
} ) ;
617
- _request ( 'https://www.linkedin.com' , function ( e , resp , body ) {
653
+ _request ( urls . linkedin_login_request , function ( e , resp , body ) {
618
654
if ( resp . statusCode !== 200 ) {
619
655
return cb ( 'Get LinkedIn session failed' ) ;
620
656
}
@@ -623,7 +659,7 @@ plugin.linkedinLogin = function(user, cb) {
623
659
return cb ( 'Get LinkedIn token failed' ) ;
624
660
}
625
661
const options = {
626
- url : 'https://www.linkedin.com/uas/login-submit' ,
662
+ url : urls . linkedin_session_request ,
627
663
method : 'POST' ,
628
664
headers : {
629
665
'Content-Type' : 'application/x-www-form-urlencoded' ,
@@ -640,14 +676,7 @@ plugin.linkedinLogin = function(user, cb) {
640
676
if ( resp . statusCode !== 200 ) {
641
677
return cb ( 'LinkedIn login failed' ) ;
642
678
}
643
- _request . get ( { url : leetcodeUrl } , function ( e , resp , body ) {
644
- const redirectUri = resp . request . uri . href ;
645
- if ( redirectUri !== 'https://leetcode.com/' ) {
646
- return cb ( 'LinkedIn login failed or LinkedIn did not link to LeetCode' ) ;
647
- }
648
- const cookieData = parseCookie ( resp . request . headers . cookie , cb ) ;
649
- saveAndGetUser ( user , cb , cookieData ) ;
650
- } ) ;
679
+ requestLeetcodeAndSave ( _request , leetcodeUrl , user , cb ) ;
651
680
} ) ;
652
681
} ) ;
653
682
} ;
0 commit comments