forked from skygragon/leetcode-cli
-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathleetcode.cn.js
124 lines (105 loc) · 3.76 KB
/
leetcode.cn.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
'use strict'
var request = require('request');
var config = require('../config');
var h = require('../helper');
var log = require('../log');
var Plugin = require('../plugin');
var session = require('../session');
//
// [Usage]
//
// https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/leetcode.cn.md
//
var plugin = new Plugin(15, 'leetcode.cn', '2018.11.25',
'Plugin to talk with leetcode-cn APIs.');
plugin.init = function() {
config.app = 'leetcode.cn';
config.sys.urls.base = 'https://leetcode-cn.com';
config.sys.urls.login = 'https://leetcode-cn.com/accounts/login/';
config.sys.urls.problems = 'https://leetcode-cn.com/api/problems/$category/';
config.sys.urls.problem = 'https://leetcode-cn.com/problems/$slug/description/';
config.sys.urls.graphql = 'https://leetcode-cn.com/graphql';
config.sys.urls.problem_detail = 'https://leetcode-cn.com/graphql';
config.sys.urls.test = 'https://leetcode-cn.com/problems/$slug/interpret_solution/';
config.sys.urls.session = 'https://leetcode-cn.com/session/';
config.sys.urls.submit = 'https://leetcode-cn.com/problems/$slug/submit/';
config.sys.urls.submissions = 'https://leetcode-cn.com/api/submissions/$slug';
config.sys.urls.submission = 'https://leetcode-cn.com/submissions/detail/$id/';
config.sys.urls.verify = 'https://leetcode-cn.com/submissions/detail/$id/check/';
config.sys.urls.favorites = 'https://leetcode-cn.com/list/api/questions';
config.sys.urls.favorite_delete = 'https://leetcode-cn.com/list/api/questions/$hash/$id';
};
// FIXME: refactor those
// update options with user credentials
function signOpts(opts, user) {
opts.headers.Cookie = 'LEETCODE_SESSION=' + user.sessionId +
';csrftoken=' + user.sessionCSRF + ';';
opts.headers['X-CSRFToken'] = user.sessionCSRF;
opts.headers['X-Requested-With'] = 'XMLHttpRequest';
}
function makeOpts(url) {
const opts = {};
opts.url = url;
opts.headers = {};
if (session.isLogin())
signOpts(opts, session.getUser());
return opts;
}
function checkError(e, resp, expectedStatus) {
if (!e && resp && resp.statusCode !== expectedStatus) {
const code = resp.statusCode;
log.debug('http error: ' + code);
if (code === 403 || code === 401) {
e = session.errors.EXPIRED;
} else {
e = {msg: 'http error', statusCode: code};
}
}
return e;
}
plugin.getProblems = function(cb) {
plugin.next.getProblems(function(e, problems) {
if (e) return cb(e);
plugin.getProblemsTitle(function(e, titles) {
if (e) return cb(e);
problems.forEach(function(problem) {
const title = titles[problem.id];
if (title)
problem.name = title;
});
return cb(null, problems);
});
});
};
plugin.getProblemsTitle = function(cb) {
log.debug('running leetcode.cn.getProblemNames');
const opts = makeOpts(config.sys.urls.graphql);
opts.headers.Origin = config.sys.urls.base;
opts.headers.Referer = 'https://leetcode-cn.com/api/problems/algorithms/';
opts.json = true;
opts.body = {
query: [
'query getQuestionTranslation($lang: String) {',
' translations: allAppliedQuestionTranslations(lang: $lang) {',
' title',
' questionId',
' __typename',
' }',
'}'
].join('\n'),
variables: {},
operationName: 'getQuestionTranslation'
};
const spin = h.spin('Downloading questions titles');
request.post(opts, function(e, resp, body) {
spin.stop();
e = checkError(e, resp, 200);
if (e) return cb(e);
const titles = [];
body.data.translations.forEach(function(x) {
titles[x.questionId] = x.title;
});
return cb(null, titles);
});
};
module.exports = plugin;