Code Duplication    Length = 65-92 lines in 2 locations

app.js 2 locations

@@ 66-157 (lines=92) @@
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
                        sem: escaper.unescape(element.eq(2).text()),
115
                        regular: escaper.unescape(element.eq(4).text()),
116
                        exam: escaper.unescape(element.eq(5).text()),
117
                        overall: escaper.unescape(element.eq(6).text())
118
                    }
119
                    if (req.query.details) {
120
                        item.id = escaper.unescape(element.eq(3).text().match(/\[.+\]/)[0].replace(/\[|\]/g, ''));
121
                        item.attr = escaper.unescape(element.eq(8).text());
122
                        item.genre = escaper.unescape(element.eq(9).text());
123
                        item.credit = escaper.unescape(element.eq(7).text());
124
                    }
125
126
                    // 如果有补考记录,则以最高分的为准
127
                    if (title in ret.grades) {
128
                        // 暂不考虑NaN
129
                        if (item.overall < ret.grades[title].overall) {
130
                            return;
131
                        }
132
                        if (!element.eq(6).css('color')) {
133
                            delete ret.failed[title];
134
                        }
135
                    } else if (element.eq(6).css('color')) {
136
                        ret.failed[title] = item;
137
                    }
138
139
                    ret.grades[title] = item;
140
                });
141
142
                ret['subject-count'] = Object.keys(ret.grades).length;
143
                ret['failed-count'] = Object.keys(ret.failed).length;
144
145
                access.logout(headers, res, function() {
146
                    // 返回JSON
147
                    res.send(JSON.stringify(ret));
148
                    fullLog && console.log((timeStamp() +
149
                        'Successfully logged out: ').green +
150
                        req.query.id.yellow +
151
                        (' (processed in ' +
152
                            (new Date() - start) + 'ms)'
153
                        ).green);
154
                });
155
            });
156
    });
157
});
158
159
// 查考试API,通过GET传入用户名和密码
160
app.get('/exams', function (req, res, next) {
@@ 160-224 (lines=65) @@
157
});
158
159
// 查考试API,通过GET传入用户名和密码
160
app.get('/exams', function (req, res, next) {
161
    if (!req.query.id || !req.query.pwd || (req.query.sem && !(/^20\d{2}-20\d{2}-[1-2]$/).test(req.query.sem))) {
162
        res.send({ error: "参数不正确" });
163
        return;
164
    }
165
    if (fullLog) {
166
        var start = new Date();
167
        console.log((timeStamp() + 'Started to query the exams: ').cyan + req.query.id.yellow);
168
    }
169
    access.login(req.query.id, req.query.pwd, res, function (headers, ires) {
170
        fullLog && console.log((timeStamp() + 'Successfully logged in.').green);
171
172
        var ret = {};
173
        var $ = cheerio.load(ires.text);
174
175
        ret.name = escaper.unescape($('.block1text').html()).match(/姓名:.+</)[0].replace('<', '').substring(3);
176
        ret.id = req.query.id;
177
        ret.sem = req.query.sem || getSem();
178
179
        superagent
180
            .post('http://csujwc.its.csu.edu.cn/jsxsd/xsks/xsksap_list')
181
            .set(headers)
182
            .type('form')
183
            .send({
184
                xqlbmc: '',
185
                xnxqid: ret.sem,
186
                xqlb: ''
187
            })
188
            .end(function (err, iires) {
189
                if (err) {
190
                    console.log((timeStamp() + 'Failed to reach exams page\n' + err.stack).red);
191
                    res.send({ error: '获取成绩失败' });
192
                    return next(err);
193
                }
194
                fullLog && console.log((timeStamp() + 'Successfully entered exams page.').green);
195
196
                $ = cheerio.load(iires.text);
197
198
                ret.exams = {};
199
                ret['exams-count'] = 0;
200
201
                $('#dataList tr').each(function (index) {
202
                    if (index === 0) {
203
                        return;
204
                    }
205
                    let element = $(this).find('td');
206
                    let title = escaper.unescape(element.eq(3).text());
207
208
                    let item = {
209
                        time: escaper.unescape(element.eq(4).text()),
210
                        location: escaper.unescape(element.eq(5).text()),
211
                        seat: escaper.unescape(element.eq(6).text())
212
                    };
213
214
                    ret.exams[title] = item;
215
                    ret['exams-count']++;
216
                });
217
218
                access.logout(headers, res, function() {
219
                    res.send(JSON.stringify(ret));
220
                    fullLog && console.log((timeStamp() + 'Successfully logged out: ').green + req.query.id.yellow + (' (processed in ' + (new Date() - start) + 'ms)').green);
221
                });
222
            });
223
    });
224
});
225
226
app.listen(port);
227
console.log((timeStamp() +