Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1f26fbd

Browse files
yihong0618jdneo
authored andcommitted
add third party github login for future updates in vscode-leetcode (#34)
1 parenta5eb30b commit1f26fbd

File tree

4 files changed

+200
-55
lines changed

4 files changed

+200
-55
lines changed

‎README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ Great thanks to leetcode.com, a really awesome website!
3838

3939
##Quick Start
4040

41-
Read help first $ leetcode help
42-
Login with your leetcode account $ leetcode user -l
43-
Cookie login with cookie $ leetcode user -c
44-
Browse all questions $ leetcode list
45-
Choose one question $ leetcode show 1 -g -l cpp
41+
Read help first $ leetcode help
42+
Login with your leetcode account $ leetcode user -l
43+
Login with third party account--GitHub $ leetcode user -g
44+
Login with third party account--LinkedIn $ leetcode user -i
45+
Cookie login with cookie $ leetcode user -c
46+
Browse all questions $ leetcode list
47+
Choose one question $ leetcode show 1 -g -l cpp
4648
Coding it!
47-
Run test(s) and pray... $ leetcode test ./two-sum.cpp -t '[3,2,4]\n7'
48-
Submit final solution! $ leetcode submit ./two-sum.cpp
49+
Run test(s) and pray...$ leetcode test ./two-sum.cpp -t '[3,2,4]\n7'
50+
Submit final solution!$ leetcode submit ./two-sum.cpp

‎lib/commands/user.js

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,42 @@ const cmd = {
1515
desc:'Manage account',
1616
builder:function(yargs){
1717
returnyargs
18-
.option('l',{
19-
alias:'login',
20-
type:'boolean',
21-
default:false,
22-
describe:'Login'
23-
})
24-
.option('c',{
25-
alias:'cookie',
26-
type:'boolean',
27-
default:false,
28-
describe:'cookieLogin'
29-
})
30-
.option('L',{
31-
alias:'logout',
32-
type:'boolean',
33-
default:false,
34-
describe:'Logout'
35-
})
36-
.example(chalk.yellow('leetcode user'),'Show current user')
37-
.example(chalk.yellow('leetcode user -l'),'User login')
38-
.example(chalk.yellow('leetcode user -c'),'User Cookie login')
39-
.example(chalk.yellow('leetcode user -L'),'User logout');
18+
.option('l',{
19+
alias:'login',
20+
type:'boolean',
21+
default:false,
22+
describe:'Login'
23+
})
24+
.option('c',{
25+
alias:'cookie',
26+
type:'boolean',
27+
default:false,
28+
describe:'cookieLogin'
29+
})
30+
.option('g',{
31+
alias:'github',
32+
type:'boolean',
33+
default:false,
34+
describe:'githubLogin'
35+
})
36+
.option('i',{
37+
alias:'linkedin',
38+
type:'boolean',
39+
default:false,
40+
describe:'linkedinLogin'
41+
})
42+
.option('L',{
43+
alias:'logout',
44+
type:'boolean',
45+
default:false,
46+
describe:'Logout'
47+
})
48+
.example(chalk.yellow('leetcode user'),'Show current user')
49+
.example(chalk.yellow('leetcode user -l'),'User login')
50+
.example(chalk.yellow('leetcode user -c'),'User Cookie login')
51+
.example(chalk.yellow('leetcode user -g'),'User GitHub login')
52+
.example(chalk.yellow('leetcode user -i'),'User LinkedIn login')
53+
.example(chalk.yellow('leetcode user -L'),'User logout');
4054
}
4155
};
4256

@@ -66,6 +80,32 @@ cmd.handler = function(argv) {
6680
log.info('Successfully logout as',chalk.yellow(user.name));
6781
else
6882
log.fail('You are not login yet?');
83+
// third parties
84+
}elseif(argv.github||argv.linkedin){
85+
// add future third parties here
86+
constfunctionMap=newMap(
87+
[
88+
['g',core.githubLogin],
89+
['github',core.githubLogin],
90+
['i',core.linkedinLogin],
91+
['linkedin',core.linkedinLogin],
92+
]
93+
);
94+
constkeyword=Object.entries(argv).filter((i)=>(i[1]===true))[0][0];
95+
constcoreFunction=functionMap.get(keyword);
96+
prompt.colors=false;
97+
prompt.message='';
98+
prompt.start();
99+
prompt.get([
100+
{name:'login',required:true},
101+
{name:'pass',required:true,hidden:true}
102+
],function(e,user){
103+
if(e)returnlog.fail(e);
104+
coreFunction(user,function(e,user){
105+
if(e)returnlog.fail(e);
106+
log.info('Successfully third party login as',chalk.yellow(user.name));
107+
});
108+
});
69109
}elseif(argv.cookie){
70110
// session
71111
prompt.colors=false;
@@ -75,22 +115,22 @@ cmd.handler = function(argv) {
75115
{name:'login',required:true},
76116
{name:'cookie',required:true}
77117
],function(e,user){
78-
if(e)returnlog.fail(e)
79-
core.cookieLogin(user,function(e,user){
80118
if(e)returnlog.fail(e);
81-
log.info('Successfully cookie login as',chalk.yellow(user.name));
119+
core.cookieLogin(user,function(e,user){
120+
if(e)returnlog.fail(e);
121+
log.info('Successfully cookie login as',chalk.yellow(user.name));
82122
});
83123
});
84-
}else{
124+
}else{
85125
// show current user
86126
user=session.getUser();
87127
if(user){
88128
log.info(chalk.gray(sprintf(' %-9s %-20s %s','Premium','User','Host')));
89129
log.info(chalk.gray('-'.repeat(60)));
90130
log.printf(' %s %-20s %s',
91-
h.prettyText('',user.paid||false),
92-
chalk.yellow(user.name),
93-
config.sys.urls.base);
131+
h.prettyText('',user.paid||false),
132+
chalk.yellow(user.name),
133+
config.sys.urls.base);
94134
}else
95135
returnlog.fail('You are not login yet?');
96136
}

‎lib/config.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ const DEFAULT_CONFIG = {
3434
base:'https://leetcode.com',
3535
graphql:'https://leetcode.com/graphql',
3636
login:'https://leetcode.com/accounts/login/',
37+
// third part login base urls. TODO facebook google
38+
github_login:'https://leetcode.com/accounts/github/login/?next=%2F',
39+
facebook_login:'https://leetcode.com/accounts/facebook/login/?next=%2F',
40+
linkedin_login:'https://leetcode.com/accounts/linkedin_oauth2/login/?next=%2F',
3741
problems:'https://leetcode.com/api/problems/$category/',
3842
problem:'https://leetcode.com/problems/$slug/description/',
3943
test:'https://leetcode.com/problems/$slug/interpret_solution/',
@@ -79,15 +83,15 @@ function Config() {}
7983

8084
Config.prototype.init=function(){
8185
nconf.file('local',file.configFile())
82-
.add('global',{type:'literal',store:DEFAULT_CONFIG})
83-
.defaults({});
86+
.add('global',{type:'literal',store:DEFAULT_CONFIG})
87+
.defaults({});
8488

8589
constcfg=nconf.get();
8690
nconf.remove('local');
8791
nconf.remove('global');
8892

8993
// HACK: remove old style configs
90-
for(letxincfg){
94+
for(constxincfg){
9195
if(x===x.toUpperCase())deletecfg[x];
9296
}
9397
deleteDEFAULT_CONFIG.type;

‎lib/plugins/leetcode.js

Lines changed: 115 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ plugin.checkError = function(e, resp, expectedStatus) {
5151

5252
plugin.init=function(){
5353
config.app='leetcode';
54-
}
54+
};
5555

5656
plugin.getProblems=function(cb){
5757
log.debug('running leetcode.getProblems');
@@ -95,7 +95,7 @@ plugin.getCategoryProblems = function(category, cb) {
9595
}
9696

9797
constproblems=json.stat_status_pairs
98-
.filter(p=>!p.stat.question__hide)
98+
.filter((p)=>!p.stat.question__hide)
9999
.map(function(p){
100100
return{
101101
state:p.status||'None',
@@ -167,7 +167,7 @@ plugin.getProblem = function(problem, cb) {
167167
problem.testable=q.enableRunCode;
168168
problem.templateMeta=JSON.parse(q.metaData);
169169
//@si-yao: seems below property is never used.
170-
//problem.discuss = q.discussCategoryId;
170+
//problem.discuss = q.discussCategoryId;
171171

172172
returncb(null,problem);
173173
});
@@ -254,9 +254,9 @@ function formatResult(result) {
254254
};
255255

256256
x.error=_.chain(result)
257-
.pick((v,k)=>/_error$/.test(k)&&v.length>0)
258-
.values()
259-
.value();
257+
.pick((v,k)=>/_error$/.test(k)&&v.length>0)
258+
.values()
259+
.value();
260260

261261
if(/[runcode|interpret].*/.test(result.submission_id)){
262262
// It's testing
@@ -374,8 +374,8 @@ plugin.starProblem = function(problem, starred, cb) {
374374
};
375375
}else{
376376
opts.url=config.sys.urls.favorite_delete
377-
.replace('$hash',user.hash)
378-
.replace('$id',problem.id);
377+
.replace('$hash',user.hash)
378+
.replace('$id',problem.id);
379379
opts.method='DELETE';
380380
}
381381

@@ -508,7 +508,7 @@ plugin.signin = function(user, cb) {
508508
plugin.getUser=function(user,cb){
509509
plugin.getFavorites(function(e,favorites){
510510
if(!e){
511-
constf=favorites.favorites.private_favorites.find(f=>f.name==='Favorite');
511+
constf=favorites.favorites.private_favorites.find((f)=>f.name==='Favorite');
512512
if(f){
513513
user.hash=f.id_hash;
514514
user.name=favorites.user_name;
@@ -538,19 +538,118 @@ plugin.login = function(user, cb) {
538538
});
539539
};
540540

541-
plugin.cookieLogin=function(user,cb){
542-
// re pattern for cookie chrome or firefox
541+
functionparseCookie(cookie,cb){
543542
constSessionPattern=/LEETCODE_SESSION=(.+?)(;|$)/;
544543
constcsrfPattern=/csrftoken=(.+?)(;|$)/;
545-
constreSessionResult=SessionPattern.exec(user.cookie);
546-
constreCsrfResult=csrfPattern.exec(user.cookie);
544+
constreSessionResult=SessionPattern.exec(cookie);
545+
constreCsrfResult=csrfPattern.exec(cookie);
547546
if(reSessionResult===null||reCsrfResult===null){
548-
returncb('invalid cookie?')
547+
returncb('invalid cookie?');
549548
}
550-
user.sessionId=reSessionResult[1];
551-
user.sessionCSRF=reCsrfResult[1];
549+
return{
550+
sessionId:reSessionResult[1],
551+
sessionCSRF:reCsrfResult[1],
552+
};
553+
}
554+
555+
functionsaveAndGetUser(user,cb,cookieData){
556+
user.sessionId=cookieData.sessionId;
557+
user.sessionCSRF=cookieData.sessionCSRF;
552558
session.saveUser(user);
553559
plugin.getUser(user,cb);
554560
}
555561

562+
plugin.cookieLogin=function(user,cb){
563+
constcookieData=parseCookie(user.cookie,cb);
564+
user.sessionId=cookieData.sessionId;
565+
user.sessionCSRF=cookieData.sessionCSRF;
566+
session.saveUser(user);
567+
plugin.getUser(user,cb);
568+
};
569+
570+
plugin.githubLogin=function(user,cb){
571+
constleetcodeUrl=config.sys.urls.github_login;
572+
const_request=request.defaults({jar:true});
573+
_request('https://github.com/login',function(e,resp,body){
574+
constauthenticityToken=body.match(/name="authenticity_token"value="(.*?)"/);
575+
if(authenticityToken===null){
576+
returncb('Get GitHub token failed');
577+
}
578+
constoptions={
579+
url:'https://github.com/session',
580+
method:'POST',
581+
headers:{
582+
'Content-Type':'application/x-www-form-urlencoded',
583+
},
584+
followAllRedirects:true,
585+
form:{
586+
'login':user.login,
587+
'password':user.pass,
588+
'authenticity_token':authenticityToken[1],
589+
'utf8':encodeURIComponent('✓'),
590+
'commit':encodeURIComponent('Sign in')
591+
},
592+
};
593+
_request(options,function(e,resp,body){
594+
if(resp.statusCode!==200){
595+
returncb('GitHub login failed');
596+
}
597+
_request.get({url:leetcodeUrl},function(e,resp,body){
598+
constredirectUri=resp.request.uri.href;
599+
if(redirectUri!=='https://leetcode.com/'){
600+
returncb('GitHub login failed or GitHub did not link to LeetCode');
601+
}
602+
constcookieData=parseCookie(resp.request.headers.cookie,cb);
603+
saveAndGetUser(user,cb,cookieData);
604+
});
605+
});
606+
});
607+
};
608+
609+
plugin.linkedinLogin=function(user,cb){
610+
constleetcodeUrl=config.sys.urls.linkedin_login;
611+
const_request=request.defaults({
612+
jar:true,
613+
headers:{
614+
'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+
}
616+
});
617+
_request('https://www.linkedin.com',function(e,resp,body){
618+
if(resp.statusCode!==200){
619+
returncb('Get LinkedIn session failed');
620+
}
621+
constauthenticityToken=body.match(/inputname="loginCsrfParam"value="(.*)"/);
622+
if(authenticityToken===null){
623+
returncb('Get LinkedIn token failed');
624+
}
625+
constoptions={
626+
url:'https://www.linkedin.com/uas/login-submit',
627+
method:'POST',
628+
headers:{
629+
'Content-Type':'application/x-www-form-urlencoded',
630+
},
631+
followAllRedirects:true,
632+
form:{
633+
'session_key':user.login,
634+
'session_password':user.pass,
635+
'loginCsrfParam':authenticityToken[1],
636+
'trk':'guest_homepage-basic_sign-in-submit'
637+
},
638+
};
639+
_request(options,function(e,resp,body){
640+
if(resp.statusCode!==200){
641+
returncb('LinkedIn login failed');
642+
}
643+
_request.get({url:leetcodeUrl},function(e,resp,body){
644+
constredirectUri=resp.request.uri.href;
645+
if(redirectUri!=='https://leetcode.com/'){
646+
returncb('LinkedIn login failed or LinkedIn did not link to LeetCode');
647+
}
648+
constcookieData=parseCookie(resp.request.headers.cookie,cb);
649+
saveAndGetUser(user,cb,cookieData);
650+
});
651+
});
652+
});
653+
};
654+
556655
module.exports=plugin;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp