Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 04b4dc1

Browse files
committed
add third party github login for future updates in vscode-leetcode and somehow solve the recaptcha problem
1 parent a5eb30b commit 04b4dc1

File tree

4 files changed

+91
-17
lines changed

4 files changed

+91
-17
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Great thanks to leetcode.com, a really awesome website!
4040

4141
Read help first $ leetcode help
4242
Login with your leetcode account $ leetcode user -l
43+
Login with third party account--github $ leetcode user -g
4344
Cookie login with cookie $ leetcode user -c
4445
Browse all questions $ leetcode list
4546
Choose one question $ leetcode show 1 -g -l cpp

lib/commands/user.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ const cmd = {
2727
default: false,
2828
describe: 'cookieLogin'
2929
})
30+
.option('g', {
31+
alias: 'github',
32+
type: 'boolean',
33+
default: false,
34+
describe: 'githubLogin'
35+
})
3036
.option('L', {
3137
alias: 'logout',
3238
type: 'boolean',
@@ -36,6 +42,7 @@ const cmd = {
3642
.example(chalk.yellow('leetcode user'), 'Show current user')
3743
.example(chalk.yellow('leetcode user -l'), 'User login')
3844
.example(chalk.yellow('leetcode user -c'), 'User Cookie login')
45+
.example(chalk.yellow('leetcode user -g'), 'User Github login')
3946
.example(chalk.yellow('leetcode user -L'), 'User logout');
4047
}
4148
};
@@ -66,6 +73,21 @@ cmd.handler = function(argv) {
6673
log.info('Successfully logout as', chalk.yellow(user.name));
6774
else
6875
log.fail('You are not login yet?');
76+
} else if (argv.github) {
77+
// github
78+
prompt.colors = false;
79+
prompt.message = '';
80+
prompt.start();
81+
prompt.get([
82+
{name: 'login', required: true},
83+
{name: 'pass', required: true, hidden: true}
84+
], function(e, user) {
85+
if (e) return log.fail(e)
86+
core.githubLogin(user, function(e, user) {
87+
if (e) return log.fail(e);
88+
log.info('Successfully github login as', chalk.yellow(user.name));
89+
});
90+
});
6991
} else if (argv.cookie) {
7092
// session
7193
prompt.colors = false;

lib/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ 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 linkin google
38+
github_login: 'https://leetcode.com/accounts/github/login/?next=%2F',
3739
problems: 'https://leetcode.com/api/problems/$category/',
3840
problem: 'https://leetcode.com/problems/$slug/description/',
3941
test: 'https://leetcode.com/problems/$slug/interpret_solution/',

lib/plugins/leetcode.js

Lines changed: 66 additions & 17 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
const problems = 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
return cb(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-
const f = favorites.favorites.private_favorites.find(f => f.name === 'Favorite');
511+
const f = 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,68 @@ plugin.login = function(user, cb) {
538538
});
539539
};
540540

541-
plugin.cookieLogin = function(user, cb) {
542-
// re pattern for cookie chrome or firefox
541+
function parseCookie(cookie, cb) {
543542
const SessionPattern = /LEETCODE_SESSION=(.+?)(;|$)/;
544543
const csrfPattern = /csrftoken=(.+?)(;|$)/;
545-
const reSessionResult = SessionPattern.exec(user.cookie);
546-
const reCsrfResult = csrfPattern.exec(user.cookie);
544+
const reSessionResult = SessionPattern.exec(cookie);
545+
const reCsrfResult = csrfPattern.exec(cookie);
547546
if (reSessionResult === null || reCsrfResult === null) {
548-
return cb('invalid cookie?')
547+
return cb('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+
plugin.cookieLogin = function(user, cb) {
556+
const cookieData = parseCookie(user.cookie, cb);
557+
user.sessionId = cookieData.sessionId;
558+
user.sessionCSRF = cookieData.sessionCSRF;
552559
session.saveUser(user);
553560
plugin.getUser(user, cb);
554-
}
561+
};
562+
563+
plugin.githubLogin = function(user, cb) {
564+
const leetcodeUrl = config.sys.urls.github_login;
565+
const _request = request.defaults({jar: true});
566+
_request('https://github.com/login', function(e, resp, body) {
567+
const authenticityToken = body.match(/name="authenticity_token" value="(.*?)"/);
568+
if (authenticityToken === null) {
569+
return cb('Get github token failed');
570+
}
571+
const options = {
572+
url: 'https://github.com/session',
573+
method: 'POST',
574+
headers: {
575+
'Content-Type': 'application/x-www-form-urlencoded',
576+
},
577+
followAllRedirects: true,
578+
form: {
579+
'login': user.login,
580+
'password': user.pass,
581+
'authenticity_token': authenticityToken[1],
582+
'utf8': encodeURIComponent('✓'),
583+
'commit': encodeURIComponent('Sign in')
584+
},
585+
};
586+
_request(options, function(e, resp, body) {
587+
if (resp.statusCode !== 200) {
588+
return cb('Github login failed');
589+
}
590+
_request.get({url: leetcodeUrl}, function(e, resp, body) {
591+
const redirectUri = resp.request.uri.href;
592+
if (redirectUri !== 'https://leetcode.com/') {
593+
return cb('Github login failed or github did not link to leetcode');
594+
}
595+
const cookieData = parseCookie(resp.request.headers.cookie, cb);
596+
user.sessionId = cookieData.sessionId;
597+
user.sessionCSRF = cookieData.sessionCSRF;
598+
session.saveUser(user);
599+
plugin.getUser(user, cb);
600+
});
601+
});
602+
});
603+
};
555604

556605
module.exports = plugin;

0 commit comments

Comments
 (0)