1 | /* TODO |
||
2 | * 完善异常处理 |
||
3 | */ |
||
4 | |||
5 | "use strict"; |
||
6 | |||
7 | var express = require('express'), |
||
8 | superagent = require('superagent'), |
||
9 | cheerio = require('cheerio'), |
||
10 | escaper = require('true-html-escape'), |
||
11 | colors = require('colors'), |
||
12 | program = require('commander'), |
||
13 | Date = require('./lib/Date.js'), |
||
14 | access = require('./lib/access.js'); |
||
15 | |||
16 | program |
||
17 | .option('-h, --help') |
||
18 | .option('-v, --version') |
||
19 | .option('-p, --port [n]', parseInt) |
||
20 | .option('-f, --fullLog') |
||
21 | .parse(process.argv); |
||
22 | |||
23 | // 别问我为什么这里逻辑这么奇怪……测试的结果确实是这样的啊hhh |
||
24 | if (!program.help || !program.version) { |
||
25 | console.log(('CSUEMS API v1.0.0').rainbow); |
||
26 | console.log(('by The Liberators').rainbow); |
||
27 | if (!program.help) { |
||
28 | console.log('Preparation:'); |
||
29 | console.log(' \\\\This section is WIP\\\\'); |
||
30 | console.log('\nUsage:'); |
||
31 | console.log(' npm start [-- <options...>]'); |
||
32 | console.log('\nOptions:'); |
||
33 | console.log(' -h, --help print this message and exit.'); |
||
34 | console.log(' -v, --version print the version and exit.'); |
||
35 | console.log(' -f, --fullLog enable full log, by default only errors are logged.'); |
||
36 | console.log(' -p, --port [value] specify a port to listen, 2333 by default.'); |
||
37 | console.log('\nExamples:'); |
||
38 | console.log(' $ npm start -p 43715 # listening to 43715'); |
||
39 | console.log(' $ sudo forever start app.js # deploy with forever as daemon (root access recommended)'); |
||
40 | console.log(' $ sudo pm2 start -i 0 --name "csuapi" app.js # deploy with pm2 as daemon (root access recommended)'); |
||
41 | } |
||
42 | process.exit(0); |
||
43 | } |
||
44 | |||
45 | const timeStamp = () => new Date().format('[MM-dd hh:mm:ss] '), |
||
46 | port = program.port || 2333, |
||
47 | base = 'http://csujwc.its.csu.edu.cn'; |
||
48 | |||
49 | var app = express(); |
||
50 | |||
51 | // 查成绩API,通过GET传入用户名和密码 |
||
52 | View Code Duplication | app.get('/grades/', function (req, res, next) { |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
53 | if (program.fulllog) { |
||
54 | var start = new Date(); |
||
55 | console.log((timeStamp() + 'Started to query the grades: ').cyan + req.query.id.yellow); |
||
56 | } |
||
57 | access.login(req.query.id, req.query.pwd, res, function (headers, ires) { |
||
58 | program.fulllog && console.log((timeStamp() + 'Successfully logged in.').green); |
||
59 | var ret = {}; |
||
60 | var $ = cheerio.load(ires.text); |
||
61 | ret.name = escaper.unescape($('.block1text').html()).match(/姓名:.+</)[0].replace('<', '').substring(3); |
||
62 | ret.id = req.query.id; |
||
63 | |||
64 | // 进入成绩页面 |
||
65 | superagent.get(base + $('li[title="我的成绩"] a').attr('href')) |
||
66 | .set(headers) |
||
67 | .end(function (err, iires) { |
||
68 | if (err) { |
||
69 | console.log((timeStamp() + 'Failed to get grades page\n' + err.stack).red); |
||
1 ignored issue
–
show
|
|||
70 | res.send({ error: '无法进入成绩页面' }); |
||
71 | return next(err); |
||
72 | } |
||
73 | program.fulllog && console.log((timeStamp() + 'Successfully entered grades page.').green); |
||
74 | |||
75 | $ = cheerio.load(iires.text); |
||
76 | |||
77 | // 获取成绩列表 |
||
78 | let grades = {}; |
||
79 | let failed = {}; |
||
80 | $('#dataList').each(function (index) { |
||
81 | // cheerio没有实现jQuery的lt |
||
82 | if (index >= 2) |
||
83 | return; |
||
84 | $(this).find('tr[class!="theadCss"]').each(function() { |
||
85 | // 这段写得真是要吐血了 |
||
86 | let subject = escaper.unescape($(this).find('td[align="left"]').eq(1).text()); |
||
87 | if (subject) { |
||
88 | let score = $(this).find('font'); |
||
89 | if (score.text()) |
||
90 | grades[subject] = score.text(); |
||
91 | if (score.css('color')) |
||
92 | failed[subject] = score.text(); |
||
93 | } |
||
94 | }); |
||
95 | }); |
||
96 | ret.grades = grades; |
||
97 | ret['subject-count'] = Object.getOwnPropertyNames(grades).length; |
||
98 | ret.failed = failed; |
||
99 | ret['failed-count'] = Object.getOwnPropertyNames(failed).length; |
||
100 | |||
101 | // 完成所有工作后,登出 |
||
102 | access.logout(headers, res, function() { |
||
103 | // 第五步:返回JSON |
||
104 | res.send(JSON.stringify(ret)); |
||
105 | program.fulllog && console.log((timeStamp() + 'Successfully logged out: ').green + req.query.id.yellow + (' (processed in ' + (new Date() - start) + 'ms)').green); |
||
106 | }); |
||
107 | }); |
||
108 | }); |
||
109 | }); |
||
110 | |||
111 | // TODO: 对参数的正确性进行检查 |
||
112 | |||
113 | // 查考试API,通过GET传入用户名和密码 |
||
114 | View Code Duplication | app.get('/exams/', function (req, res, next) { |
|
0 ignored issues
–
show
|
|||
115 | if (program.fulllog) { |
||
116 | var start = new Date(); |
||
117 | console.log((timeStamp() + 'Started to query the exams: ').cyan + req.query.id.yellow); |
||
1 ignored issue
–
show
|
|||
118 | } |
||
119 | access.login(req.query.id, req.query.pwd, res, function (headers, ires) { |
||
120 | var ret = {}; |
||
121 | var $ = cheerio.load(ires.text); |
||
122 | ret.name = escaper.unescape($('.block1text').html()).match(/姓名:.+</)[0].replace('<', '').substring(3); |
||
123 | ret.id = req.query.id; |
||
124 | |||
125 | superagent.post('http://csujwc.its.csu.edu.cn/jsxsd/xsks/xsksap_list') |
||
126 | .set(headers) |
||
127 | .type('form') |
||
128 | .send({ |
||
129 | xqlbmc: '', |
||
130 | xnxqid: '2016-2017-1', //TODO: 添加别的选项,或者通过参数传入 |
||
131 | xqlb: '' |
||
132 | }) |
||
133 | .end(function (err, iires) { |
||
134 | if (err) { |
||
135 | console.log((timeStamp() + 'Failed to reach exams page\n' + err.stack).red); |
||
1 ignored issue
–
show
|
|||
136 | res.send({ error: '获取成绩失败' }); |
||
137 | return next(err); |
||
138 | } |
||
139 | program.fulllog && console.log((timeStamp() + 'Successfully entered exams page.').green); |
||
140 | |||
141 | $ = cheerio.load(iires.text); |
||
142 | |||
143 | let exams = []; |
||
144 | |||
145 | $('#dataList tr').each(function (index) { |
||
146 | if (index === 0) |
||
147 | 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. ![]() |
|||
148 | let item = $(this).find('td'); |
||
149 | let subject = {}; |
||
150 | subject.subject = escaper.unescape(item.eq(3).text()); |
||
151 | subject.time = escaper.unescape(item.eq(4).text()); |
||
152 | subject.location = escaper.unescape(item.eq(5).text()); |
||
153 | subject.seat = escaper.unescape(item.eq(6).text()); |
||
154 | exams.push(subject); |
||
155 | }); |
||
156 | |||
157 | ret.exams = exams; |
||
158 | |||
159 | access.logout(headers, res, function() { |
||
160 | res.send(JSON.stringify(ret)); |
||
161 | program.fulllog && console.log((timeStamp() + 'Successfully logged out: ').green + req.query.id.yellow + (' (processed in ' + (new Date() - start) + 'ms)').green); |
||
1 ignored issue
–
show
|
|||
162 | }); |
||
0 ignored issues
–
show
|
|||
163 | }); |
||
164 | }); |
||
165 | }); |
||
166 | |||
167 | app.listen(port); |
||
168 | console.log((timeStamp() + 'The server is now running on port ' + port + '.').green); |