Skip to content

Commit 3d6e91c

Browse files
committed
Auto re-login if session is expired.
* if config.AUTO_LOGIN is true, user password will be saved locally and used to re-login w/o manually intervened. * if config.AUTO_LOGIN is false, user password will not be saved. If session expired, user need to manually login again. Signed-off-by: Eric Wang <[email protected]>
1 parent e0a657a commit 3d6e91c

File tree

3 files changed

+61
-14
lines changed

3 files changed

+61
-14
lines changed

lib/config.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ var defaultConfig = {
1414
VERIFY_URL: 'https://leetcode.com/submissions/detail/$id/check/',
1515

1616
// but you will want change these
17-
LANG: 'cpp', // avail: [c,cpp,csharp,golang,java,javascript,python,ruby,swift]
18-
USE_COLOR: true
17+
LANG: 'cpp', // avail: [c,cpp,csharp,golang,java,javascript,python,ruby,swift]
18+
USE_COLOR: true,
19+
AUTO_LOGIN: true
1920
};
2021

2122
function initConfig() {

lib/core.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
var _ = require('underscore');
22

33
var cache = require('./cache');
4+
var config = require('./config');
45
var client = require('./leetcode_client');
56

67
var core = {};
@@ -69,7 +70,12 @@ core.login = function(user, cb) {
6970

7071
self.logout();
7172

72-
cache.set('.user', _.omit(user, 'pass'));
73+
if (config.AUTO_LOGIN)
74+
// need save password thus we can auto re-login later
75+
cache.set('.user', user);
76+
else
77+
cache.set('.user', _.omit(user, 'pass'));
78+
7379
return cb(null, user);
7480
});
7581
};

lib/leetcode_client.js

+51-11
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ var request = require('request');
44
var config = require('./config');
55
var h = require('./helper');
66

7+
// update options with user credentials
8+
function signOpts(opts, user) {
9+
opts.headers.Cookie = 'PHPSESSID=' + user.sessionId +
10+
';csrftoken=' + user.sessionCSRF + ';';
11+
opts.headers['X-CSRFToken'] = user.sessionCSRF;
12+
}
13+
714
function makeOpts(url) {
8-
var opts = {url: url, headers: {}};
15+
var opts = {url: url, headers: {}, _expectedStatus: 200};
916
var core = require('./core');
10-
if (core.isLogin()) {
11-
var user = core.getUser();
12-
opts.headers.Cookie = 'PHPSESSID=' + user.sessionId +
13-
';csrftoken=' + user.sessionCSRF + ';';
14-
opts.headers['X-CSRFToken'] = user.sessionCSRF;
15-
}
17+
if (core.isLogin()) signOpts(opts, core.getUser());
1618
return opts;
1719
}
1820

@@ -34,10 +36,44 @@ function checkError(e, resp, expectedStatus, msg) {
3436
}
3537
}
3638

39+
// leetcode.com is limiting one session alive in the same time,
40+
// which means once you login on web, your cli session will get
41+
// expired immediately. In that case we will try to re-login in
42+
// the backend to give a seamless user experience.
43+
function requestWithReLogin(opts, cb) {
44+
if (!config.AUTO_LOGIN)
45+
return request(opts, cb);
46+
47+
var core = require('./core');
48+
var user = core.getUser();
49+
50+
request(opts, function(e, resp, body) {
51+
e = checkError(e, resp, opts._expectedStatus);
52+
53+
// not 403: transparently pass down
54+
if (!e || e.statusCode !== 403)
55+
return cb(e, resp, body);
56+
57+
// if 403: try re-login
58+
console.log('session expired, auto re-login...');
59+
60+
core.login(user, function(e2, user) {
61+
if (e2) return cb(e, resp, body);
62+
63+
console.log('login successfully, cont\'d...');
64+
signOpts(opts, user);
65+
66+
request(opts, cb);
67+
});
68+
});
69+
}
70+
3771
var leetcodeClient = {};
3872

3973
leetcodeClient.getProblems = function(cb) {
40-
request(makeOpts(config.PROBLEMS_URL), function(e, resp, body) {
74+
var opts = makeOpts(config.PROBLEMS_URL);
75+
76+
requestWithReLogin(opts, function(e, resp, body) {
4177
e = checkError(e, resp, 200);
4278
if (e) return cb(e);
4379

@@ -135,8 +171,10 @@ function verifyResult(opts, jobs, results, cb) {
135171
if (jobs.length === 0)
136172
return cb(null, results);
137173

174+
opts.method = 'GET';
138175
opts.url = config.VERIFY_URL.replace('$id', jobs[0].id);
139-
request.get(opts, function(e, resp, body) {
176+
177+
requestWithReLogin(opts, function(e, resp, body) {
140178
e = checkError(e, resp, 200);
141179
if (e) return cb(e);
142180

@@ -153,6 +191,7 @@ function verifyResult(opts, jobs, results, cb) {
153191

154192
leetcodeClient.testProblem = function(problem, cb) {
155193
var opts = makeOpts();
194+
opts.method = 'POST';
156195
opts.url = config.TEST_URL.replace('$key', problem.key);
157196
opts.headers.Origin = config.BASE_URL;
158197
opts.headers.Referer = problem.link;
@@ -166,7 +205,7 @@ leetcodeClient.testProblem = function(problem, cb) {
166205
'typed_code': h.getFileData(problem.file)
167206
};
168207

169-
request.post(opts, function(e, resp, body) {
208+
requestWithReLogin(opts, function(e, resp, body) {
170209
e = checkError(e, resp, 200);
171210
if (e) return cb(e);
172211

@@ -183,6 +222,7 @@ leetcodeClient.testProblem = function(problem, cb) {
183222

184223
leetcodeClient.submitProblem = function(problem, cb) {
185224
var opts = makeOpts();
225+
opts.method = 'POST';
186226
opts.url = config.SUBMIT_URL.replace('$key', problem.key);
187227
opts.headers.Origin = config.BASE_URL;
188228
opts.headers.Referer = problem.link;
@@ -196,7 +236,7 @@ leetcodeClient.submitProblem = function(problem, cb) {
196236
'typed_code': h.getFileData(problem.file)
197237
};
198238

199-
request.post(opts, function(e, resp, body) {
239+
requestWithReLogin(opts, function(e, resp, body) {
200240
e = checkError(e, resp, 200);
201241
if (e) return cb(e);
202242

0 commit comments

Comments
 (0)