Code Duplication    Length = 71-85 lines in 2 locations

app.js 2 locations

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