Code Duplication    Length = 64-91 lines in 2 locations

app.js 2 locations

@@ 66-156 (lines=91) @@
63
var app = express();
64
65
// 查成绩API,通过GET传入用户名和密码
66
app.get('/grades', function (req, res, next) {
67
    if (!req.query.id || !req.query.pwd || (req.query.sem && !(/^20\d{2}-20\d{2}-[1-2]$/).test(req.query.sem))) {
68
        res.send({ error: "参数不正确" });
69
        return;
70
    }
71
    if (fullLog) {
72
        var start = new Date();
73
        console.log((timeStamp() + 'Started to query the grades: ').cyan + req.query.id.yellow);
74
    }
75
    access.login(req.query.id, req.query.pwd, res, function (headers, ires) {
76
        fullLog && console.log((timeStamp() + 'Successfully logged in.').green);
77
78
        var ret = {};
79
        var $ = cheerio.load(ires.text);
80
81
        ret.name = escaper.unescape($('.block1text').html()).match(/姓名:.+</)[0].substring(3).replace(/</, '');
82
        ret.id = req.query.id;
83
84
        // 实际上xnxq01id为空的时候和GET这个URL的效果是一样的,都是查询所有学期
85
        superagent
86
            .post('http://csujwc.its.csu.edu.cn/jsxsd/kscj/yscjcx_list')
87
            .set(headers)
88
            .type('form')
89
            .send({
90
                xnxq01id: req.query.sem
91
            })
92
            .end(function (err, iires) {
93
                if (err) {
94
                    console.log((timeStamp() + 'Failed to get grades page\n' + err.stack).red);
95
                    res.send({ error: '无法进入成绩页面' });
96
                    return next(err);
97
                }
98
                fullLog && console.log((timeStamp() + 'Successfully entered grades page.').green);
99
100
                $ = cheerio.load(iires.text);
101
                
102
                ret.grades = {};
103
                ret.failed = {};
104
105
                // 获取成绩列表
106
                $('#dataList tr').each(function (index) {
107
                    if (index === 0) {
108
                        return;
109
                    }
110
                    let element = $(this).find('td');
111
                    let title = escaper.unescape(element.eq(3).text().match(/].+$/)[0].substring(1));
112
113
                    let item = {};
114
                    item.sem = escaper.unescape(element.eq(2).text());
115
                    item.regular = escaper.unescape(element.eq(4).text());
116
                    item.exam = escaper.unescape(element.eq(5).text());
117
                    item.overall = escaper.unescape(element.eq(6).text());
118
                    if (req.query.details) {
119
                        item.id = escaper.unescape(element.eq(3).text().match(/\[.+\]/)[0].replace(/\[|\]/g, ''));
120
                        item.attr = escaper.unescape(element.eq(8).text());
121
                        item.genre = escaper.unescape(element.eq(9).text());
122
                        item.credit = escaper.unescape(element.eq(7).text());
123
                    }
124
125
                    // 如果有补考记录,则以最高分的为准
126
                    if (title in ret.grades) {
127
                        // 暂不考虑NaN
128
                        if (item.overall < ret.grades[title].overall) {
129
                            return;
130
                        }
131
                        if (!element.eq(6).css('color')) {
132
                            delete ret.failed[title];
133
                        }
134
                    } else if (element.eq(6).css('color')) {
135
                        ret.failed[title] = item;
136
                    }
137
138
                    ret.grades[title] = item;
139
                });
140
141
                ret['subject-count'] = Object.keys(ret.grades).length;
142
                ret['failed-count'] = Object.keys(ret.failed).length;
143
144
                access.logout(headers, res, function() {
145
                    // 返回JSON
146
                    res.send(JSON.stringify(ret));
147
                    fullLog && console.log((timeStamp() +
148
                        'Successfully logged out: ').green +
149
                        req.query.id.yellow +
150
                        (' (processed in ' +
151
                            (new Date() - start) + 'ms)'
152
                        ).green);
153
                });
154
            });
155
    });
156
});
157
158
// 查考试API,通过GET传入用户名和密码
159
app.get('/exams', function (req, res, next) {
@@ 159-222 (lines=64) @@
156
});
157
158
// 查考试API,通过GET传入用户名和密码
159
app.get('/exams', function (req, res, next) {
160
    if (!req.query.id || !req.query.pwd || (req.query.sem && !(/^20\d{2}-20\d{2}-[1-2]$/).test(req.query.sem))) {
161
        res.send({ error: "参数不正确" });
162
        return;
163
    }
164
    if (fullLog) {
165
        var start = new Date();
166
        console.log((timeStamp() + 'Started to query the exams: ').cyan + req.query.id.yellow);
167
    }
168
    access.login(req.query.id, req.query.pwd, res, function (headers, ires) {
169
        fullLog && console.log((timeStamp() + 'Successfully logged in.').green);
170
171
        var ret = {};
172
        var $ = cheerio.load(ires.text);
173
174
        ret.name = escaper.unescape($('.block1text').html()).match(/姓名:.+</)[0].replace('<', '').substring(3);
175
        ret.id = req.query.id;
176
        ret.sem = req.query.sem || getSem();
177
178
        superagent
179
            .post('http://csujwc.its.csu.edu.cn/jsxsd/xsks/xsksap_list')
180
            .set(headers)
181
            .type('form')
182
            .send({
183
                xqlbmc: '',
184
                xnxqid: ret.sem,
185
                xqlb: ''
186
            })
187
            .end(function (err, iires) {
188
                if (err) {
189
                    console.log((timeStamp() + 'Failed to reach exams page\n' + err.stack).red);
190
                    res.send({ error: '获取成绩失败' });
191
                    return next(err);
192
                }
193
                fullLog && console.log((timeStamp() + 'Successfully entered exams page.').green);
194
195
                $ = cheerio.load(iires.text);
196
197
                ret.exams = {};
198
                ret['exams-count'] = 0;
199
200
                $('#dataList tr').each(function (index) {
201
                    if (index === 0) {
202
                        return;
203
                    }
204
                    let element = $(this).find('td');
205
                    let title = escaper.unescape(element.eq(3).text());
206
207
                    let item = {};
208
                    item.time = escaper.unescape(element.eq(4).text());
209
                    item.location = escaper.unescape(element.eq(5).text());
210
                    item.seat = escaper.unescape(element.eq(6).text());
211
212
                    ret.exams[title] = item;
213
                    ret['exams-count']++;
214
                });
215
216
                access.logout(headers, res, function() {
217
                    res.send(JSON.stringify(ret));
218
                    fullLog && console.log((timeStamp() + 'Successfully logged out: ').green + req.query.id.yellow + (' (processed in ' + (new Date() - start) + 'ms)').green);
219
                });
220
            });
221
    });
222
});
223
224
app.listen(port);
225
console.log((timeStamp() +