1 | var http = require('http'), |
||
2 | express = require('express'), |
||
3 | superagent = require('superagent'), |
||
4 | cheerio = require('cheerio'), |
||
5 | escaper = require('true-html-escape'), |
||
6 | colors = require('colors'), |
||
7 | program = require('commander'), |
||
8 | Date = require('./lib/Date.js'); |
||
0 ignored issues
–
show
Comprehensibility
introduced
by
![]() |
|||
9 | |||
10 | program |
||
11 | .option('-h, --help') |
||
12 | .option('-v, --version') |
||
13 | .option('-p, --port [n]', parseInt) |
||
0 ignored issues
–
show
The variable
parseInt seems to be never declared. If this is a global, consider adding a /** global: parseInt */ comment.
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed. To learn more about declaring variables in Javascript, see the MDN. ![]() |
|||
14 | .option('-f, --fulllog') |
||
15 | .parse(process.argv); |
||
16 | |||
17 | // 别问我为什么这里逻辑这么奇怪……测试的结果确实是这样的啊hhh |
||
18 | if (!program.help || !program.version) { |
||
19 | console.log(('CSUEMS API v1.0.0').rainbow); |
||
1 ignored issue
–
show
|
|||
20 | console.log(('by The Liberators').rainbow); |
||
21 | if (!program.help) { |
||
22 | console.log('Preparation:') |
||
23 | console.log(' \\\\This section is WIP\\\\'); |
||
24 | console.log('\nUsage:'); |
||
25 | console.log(' npm start [-- <options>]'); |
||
26 | console.log('\nOptions:'); |
||
27 | console.log(' -h, --help print this message and exit.'); |
||
28 | console.log(' -v, --version print the version and exit.'); |
||
29 | console.log(' -f, --fulllog enable full log, by default only errors are logged.'); |
||
30 | console.log(' -p, --port [value] specify a port to listen, 2333 by default.'); |
||
31 | console.log('\nExamples:'); |
||
32 | console.log(' $ npm start -p 43715 # listening to 43715'); |
||
33 | console.log(' # forever start app.js # deploy with forever as daemon (root access recommended)'); |
||
34 | console.log(' # pm2 start app.js -i 0 --name "CSUEMSR" # deploy with pm2 as daemon (root access recommended)'); |
||
35 | } |
||
36 | process.exit(0); |
||
1 ignored issue
–
show
Compatibility
Debugging Code
Best Practice
introduced
by
|
|||
37 | } |
||
38 | |||
39 | const timeStamp = () => new Date().format('[MM-dd hh:mm:ss] '), |
||
40 | port = program.port || 2333; |
||
41 | base = 'http://csujwc.its.csu.edu.cn'; |
||
0 ignored issues
–
show
|
|||
42 | |||
43 | // 直接从主页上扒下来的,哈希算法 |
||
44 | const encodeInp = (input) => { |
||
45 | let keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; |
||
46 | let output = ""; |
||
47 | let chr1, chr2, chr3 = ""; |
||
48 | let enc1, enc2, enc3, enc4 = ""; |
||
49 | let i = 0; |
||
50 | do { |
||
51 | chr1 = input.charCodeAt(i++); |
||
52 | chr2 = input.charCodeAt(i++); |
||
53 | chr3 = input.charCodeAt(i++); |
||
54 | enc1 = chr1 >> 2; |
||
55 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); |
||
56 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); |
||
57 | enc4 = chr3 & 63; |
||
58 | if (isNaN(chr2)) { |
||
59 | enc3 = enc4 = 64 |
||
60 | } else if (isNaN(chr3)) { |
||
61 | enc4 = 64 |
||
62 | } |
||
63 | output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); |
||
64 | chr1 = chr2 = chr3 = ""; |
||
0 ignored issues
–
show
|
|||
65 | enc1 = enc2 = enc3 = enc4 = "" |
||
0 ignored issues
–
show
|
|||
66 | } while (i < input.length); |
||
67 | return output; |
||
68 | }; |
||
69 | |||
70 | // 登出时用到的函数,一样是从原网页扒下来的 |
||
71 | const getRandomUrl = (htmlurl) => { |
||
72 | let count = htmlurl.indexOf("?"); |
||
73 | let date = new Date(); |
||
74 | let t = Date.parse(date); |
||
75 | if (count < 0) { |
||
76 | htmlurl = htmlurl + "?tktime=" + t; |
||
77 | } else { |
||
78 | htmlurl = htmlurl + "&tktime=" + t; |
||
79 | } |
||
80 | return htmlurl; |
||
81 | } |
||
82 | |||
83 | // 登录模块 |
||
84 | const login = (id, pwd, res, callback) => { |
||
85 | // 通过GET首页,来获取cookie |
||
86 | superagent.get('http://csujwc.its.csu.edu.cn/jsxsd') |
||
87 | .end(function (err, ires) { |
||
88 | if (err) { |
||
89 | console.log((timeStamp() + 'Failed to get the Cookie.\n' + err.stack).red); |
||
1 ignored issue
–
show
|
|||
90 | res.send({ error: '获取Cookie失败' }); |
||
91 | return; |
||
92 | } |
||
93 | program.fulllog && console.log((timeStamp() + 'Successfully got the Cookie.').green); |
||
94 | |||
95 | // 登录POST请求的headers,是我抓包来的 |
||
96 | let headers = { |
||
97 | Host: 'csujwc.its.csu.edu.cn', |
||
98 | Connection: 'keep-alive', |
||
99 | 'Cache-Control': 'max-age=0', |
||
100 | Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', |
||
101 | Origin: 'http://csujwc.its.csu.edu.cn', |
||
102 | 'Upgrade-Insecure-Requests': 1, |
||
103 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', |
||
104 | 'Content-Type': 'application/x-www-form-urlencoded', |
||
105 | Referer: 'http://csujwc.its.csu.edu.cn/jsxsd/', |
||
106 | 'Accept-Encoding': 'gzip, deflate', |
||
107 | 'Accept-Language': 'zh-CN,zh;q=0.8', |
||
108 | Cookie: ires.headers['set-cookie'] // 猜测:感觉这个cookie也是不变的,不过出于稳定性,还是动态获取了 |
||
109 | } |
||
110 | |||
111 | let account = encodeInp(id); |
||
112 | let passwd = encodeInp(pwd); |
||
113 | let encoded = escaper.escape(account + "%%%" + passwd); |
||
114 | |||
115 | // POST登录 |
||
116 | superagent.post('http://csujwc.its.csu.edu.cn/jsxsd/xk/LoginToXk') |
||
117 | .set(headers) |
||
118 | .type('form') |
||
119 | .send({ encoded: encoded }) |
||
120 | .end(function (err, iires) { |
||
121 | // 如果登录信息正确,这里是对http://csujwc.its.csu.edu.cn/jsxsd/framework/xsMain.jsp的GET请求 |
||
122 | // 如果错误,会变成对http://csujwc.its.csu.edu.cn/jsxsd/xk/LoginToXk的POST请求 |
||
123 | if (err || /POST/i.test(iires.req.method)) { |
||
124 | console.log((timeStamp() + 'Fail to login\n' + (err ? err.stack : 'Possibily id or password provided were wrong')).red); |
||
1 ignored issue
–
show
|
|||
125 | res.send({ error: '登录失败,可能是用户名或密码错误' }); |
||
126 | return; |
||
127 | } |
||
128 | program.fulllog && console.log((timeStamp() + 'Successfully logged in.').green); |
||
129 | // 将相应的headers和返回的response(刚进去的首页)传入callback |
||
130 | callback(headers, iires); |
||
131 | }); |
||
132 | }); |
||
133 | }; |
||
134 | |||
135 | var app = express(); |
||
136 | |||
137 | // 查成绩API,通过GET传入用户名和密码 |
||
138 | app.get('/query/', function (req, res, next) { |
||
139 | if (program.fulllog) { |
||
140 | var start = new Date(); |
||
141 | console.log((timeStamp() + 'Started to proceed: ').cyan + req.query.id.yellow); |
||
1 ignored issue
–
show
|
|||
142 | } |
||
143 | login(req.query.id, req.query.pwd, res, function (headers, iires) { |
||
144 | var ret = {}; |
||
145 | var $ = cheerio.load(iires.text); |
||
146 | |||
147 | // 进入成绩页面 |
||
148 | superagent.get(base + $('li[title="我的成绩"] a').attr('href')) |
||
149 | .set(headers) |
||
150 | .end(function (err, iiires) { |
||
151 | if (err) { |
||
152 | console.log((timeStamp() + 'Fail to obtain grades\n' + err.stack).red); |
||
1 ignored issue
–
show
|
|||
153 | ret.error = '获取成绩失败'; |
||
154 | return next(err); |
||
155 | } |
||
156 | program.fulllog && console.log((timeStamp() + 'Successfully entered grades page.').green); |
||
157 | |||
158 | $ = cheerio.load(iiires.text); |
||
159 | |||
160 | // 获取成绩列表 |
||
161 | let grades = {}; |
||
162 | let failed = {}; |
||
163 | $('#dataList').each(function (index) { |
||
164 | // cheerio没有实现jQuery的lt |
||
165 | if (index >= 2) |
||
166 | return; |
||
0 ignored issues
–
show
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later. Consider: if (a > 0)
b = 42;
If you or someone else later decides to put another statement in, only the first statement will be executed. if (a > 0)
console.log("a > 0");
b = 42;
In this case the statement if (a > 0) {
console.log("a > 0");
b = 42;
}
ensures that the proper code will be executed conditionally no matter how many statements are added or removed. ![]() |
|||
167 | $(this).find('tr[class!="theadCss"]').each(function() { |
||
168 | // 这段写得真是要吐血了 |
||
169 | let subject = escaper.unescape($(this).find('td[align="left"]').eq(1).text()); |
||
170 | if (subject) { |
||
171 | let score = $(this).find('font'); |
||
172 | if (score.text()) |
||
173 | grades[subject] = score.text(); |
||
0 ignored issues
–
show
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later. Consider: if (a > 0)
b = 42;
If you or someone else later decides to put another statement in, only the first statement will be executed. if (a > 0)
console.log("a > 0");
b = 42;
In this case the statement if (a > 0) {
console.log("a > 0");
b = 42;
}
ensures that the proper code will be executed conditionally no matter how many statements are added or removed. ![]() |
|||
174 | if (score.css('color')) |
||
175 | failed[subject] = score.text(); |
||
0 ignored issues
–
show
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later. Consider: if (a > 0)
b = 42;
If you or someone else later decides to put another statement in, only the first statement will be executed. if (a > 0)
console.log("a > 0");
b = 42;
In this case the statement if (a > 0) {
console.log("a > 0");
b = 42;
}
ensures that the proper code will be executed conditionally no matter how many statements are added or removed. ![]() |
|||
176 | } |
||
177 | }); |
||
178 | }); |
||
179 | ret.grades = grades; |
||
180 | ret['subject-count'] = Object.getOwnPropertyNames(grades).length; |
||
181 | ret.failed = failed; |
||
182 | ret['failed-count'] = Object.getOwnPropertyNames(failed).length; |
||
183 | |||
184 | // 完成所有工作后,登出 |
||
185 | superagent.get(getRandomUrl(base + '/jsxsd/xk/LoginToXk?method=exit')) |
||
186 | .set(headers) |
||
187 | .end(function (err, iiiires) { |
||
0 ignored issues
–
show
|
|||
188 | if (err) { |
||
189 | console.log((timeStamp() + 'Fail to logout\n' + err.stack).red); |
||
1 ignored issue
–
show
|
|||
190 | res.send({ error: '操作失败' }); |
||
191 | return next(err); |
||
192 | } |
||
193 | |||
194 | // 第五步:返回JSON |
||
195 | res.send(JSON.stringify(ret)); |
||
196 | program.fulllog && console.log((timeStamp() + 'Successfully logged out: ').green + req.query.id.yellow + (' (total time: ' + (new Date() - start) + 'ms)').green); |
||
0 ignored issues
–
show
|
|||
197 | }); |
||
0 ignored issues
–
show
|
|||
198 | }); |
||
199 | }); |
||
200 | }); |
||
201 | |||
202 | app.listen(port); |
||
203 | console.log((timeStamp() + 'The server is now running on port ' + port + '.').green); |