Skip to content

Commit 3c84e43

Browse files
committed
feat: 91打卡功能代码优化
1 parent 1c3a1ba commit 3c84e43

File tree

4 files changed

+95
-130
lines changed

4 files changed

+95
-130
lines changed

Diff for: app.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const lectures = require("./routes/lectures");
1616
const github = require("./routes/github");
1717
const fallback = require("./routes/redirect");
1818
const my = require("./routes/my");
19-
// const lc = require("./routes/lc");
19+
const lc = require("./routes/lc");
2020
const mockUserInfo = require("./middleware/mockUserInfo");
2121

2222
// error handler
@@ -80,7 +80,7 @@ app.use(lectures.routes(), lectures.allowedMethods());
8080
app.use(dailyProblem.routes(), dailyProblem.allowedMethods());
8181
app.use(my.routes(), my.allowedMethods());
8282
app.use(github.routes(), github.allowedMethods());
83-
// app.use(lc.routes(), lc.allowedMethods());
83+
app.use(lc.routes(), lc.allowedMethods());
8484
// error-handling
8585
app.on("error", (err, ctx) => {
8686
console.error("server error", err, ctx);

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"koa-views": "^6.2.0",
2626
"mongodb": "^3.6.6",
2727
"node-fetch": "^2.6.1",
28-
"pug": "^2.0.3"
28+
"pug": "^2.0.3",
29+
"request": "^2.88.2"
2930
},
3031
"devDependencies": {
3132
"nodemon": "^1.19.1"

Diff for: routes/lc.js

+91-54
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
21
const router = require("koa-router")();
32
const fetch = require("node-fetch");
3+
const request = require('request');
44
const {
55
leetcodeConfig: {
66
baseUrl,
7+
loginUrl,
78
submitUrl,
89
_91UsernameCookieName,
910
_91PwdCookieName,
@@ -13,102 +14,93 @@ const {
1314
} = require('../config/index')
1415
const { success, fail } = require('../utils/request')
1516
const { encrypt, decrypt } = require('../utils/crypto')
16-
const { set91Cookie, getLcRequestData } = require('./utils')
1717

1818
// 用户上传lc的账号名与密码
1919
router.post('/api/v1/lc/submitLcAccount', async (ctx) => {
20-
const { login, password } = ctx.request.body
2120
// 先提交给lc,账号密码是否正确
21+
const { login, password } = ctx.request.body
2222
let result = await getLcRequestData({login, password})
2323
if(result.success){
24-
// 密码正确时,对密码进行加密
2524
let encryptPwd = encrypt(password)
26-
// 将加密后的密文 以及 sessionId、 csrftoken 写入cookie中
27-
sessionId = result[lcSeesionCookieName]
28-
csrftoken = result[lcCsrftokenCookieName]
29-
set91Cookie({
25+
ctx.body = success({
26+
isLogin: true,
3027
[_91UsernameCookieName]: login,
3128
[_91PwdCookieName]: encryptPwd,
32-
[lcSeesionCookieName]: sessionId,
33-
[lcCsrftokenCookieName]: csrftoken,
34-
}, ctx)
35-
ctx.body = success({isLogin: true})
29+
[lcSeesionCookieName]: result[lcSeesionCookieName],
30+
[lcCsrftokenCookieName]: result[lcCsrftokenCookieName],
31+
})
3632
} else {
37-
ctx.body = fail({code: 302, message: '提交失败' })
33+
ctx.body = fail({code: 302, message: result.message || '登录失败' })
3834
}
3935
});
4036

4137
// 用户提交题解
38+
// 前置数据校验
4239
router.post('/api/v1/lc/submitCode', async (ctx, next) => {
43-
// 先校验cookie中是否有账号密码,没有就让用户先输入再提交
44-
const userName = ctx.cookies.get(_91UsernameCookieName)
45-
const passwd = ctx.cookies.get(_91PwdCookieName)
46-
if(!userName || !passwd){
40+
const {
41+
login,
42+
password,
43+
[lcSeesionCookieName.toLowerCase()]: sessionId,
44+
[lcCsrftokenCookieName.toLowerCase()]: csrftoken
45+
} = ctx.request.headers
46+
// 如果有一个不存在,就提示用户重新提交一遍lc的账号密码
47+
if(!login || !password || !sessionId || !csrftoken){
4748
return ctx.response.body = fail({
4849
code: 403,
49-
message: "请先提交账号名与密码后再提交"
50+
message: "缺少字段或者cookie已过期,请重新提交账号名与密码后再提交"
5051
});
5152
}
53+
await next()
54+
})
55+
56+
// 题解提交逻辑
57+
router.post('/api/v1/lc/submitCode', async (ctx) => {
58+
const {
59+
login,
60+
password,
61+
[lcSeesionCookieName.toLowerCase()]: sessionId,
62+
[lcCsrftokenCookieName.toLowerCase()]: csrftoken
63+
} = ctx.request.headers
64+
const lcAccountData = {
65+
login,
66+
password,
67+
}
5268

53-
// 如果这俩cookie有一个不存在就提示用户重新提交一遍lc的账号密码
54-
let sessionId = ctx.cookies.get(lcSeesionCookieName)
55-
let csrftoken = ctx.cookies.get(lcCsrftokenCookieName)
69+
// 先试着用旧值提交下看是否成功
70+
const problemData = formateSubmitData(ctx.request.body)
5671
let requestData = {
5772
[lcSeesionCookieName]: sessionId,
5873
[lcCsrftokenCookieName]: csrftoken
5974
}
60-
if(!sessionId || !csrftoken){
61-
return ctx.response.body = fail({
62-
code: 403,
63-
message: "提交失败,请重新输入账号名与密码后再提交!"
64-
});
65-
}
66-
67-
// 先试着用cookie中的旧csrftoken提交下看是否成功
68-
const problemData = formateSubmitData(ctx.request.body)
6975
let result = (await submitSolution(problemData, requestData)) || {}
70-
if(result.success){
71-
return ctx.body = success(result.data)
76+
if(result.success && result.data.submission_id){
77+
return ctx.response.body = success(Object.assign(requestData, result.data, lcAccountData))
7278
}
7379

7480
// 如果403就用账号密码获取最新csrftoken,再提交一遍
7581
if(result.statusCode === 403){
76-
// 获取最新csrftoken
77-
let newRequestData = await getLatestLcRequestData(ctx)
82+
const decryPwd = decrypt(password)
83+
let newRequestData = await getLcRequestData({
84+
[_91UsernameCookieName]: login,
85+
[_91PwdCookieName]: decryPwd
86+
})
7887
if(!newRequestData.success){
7988
return ctx.response.body = fail({
8089
code: 403,
8190
message: newRequestData.message || "提交失败,请重新输入账号名与密码后再提交!"
8291
});
8392
}
84-
// 更新下91的cookie
85-
set91Cookie(newRequestData, ctx)
86-
87-
// 再提交一遍
8893
let retryResult = await submitSolution(problemData, newRequestData)
89-
if(retryResult.success){
90-
return ctx.body = success(retryResult.data)
94+
if(retryResult.success && retryResult.data.submission_id){
95+
return ctx.body = success(Object.assign(newRequestData, retryResult.data, lcAccountData))
9196
}
9297
}
93-
94-
// 如果还是失败,就提示用户重新输入账号名与密码
9598
return ctx.response.body = fail({
9699
code: 403,
97100
message: "提交失败,请重新输入账号名与密码后再提交!"
98101
});
99102
});
100103

101-
// 获取最新的的向leetcode发送请求的必要参数
102-
async function getLatestLcRequestData(ctx){
103-
const userName = ctx.cookies.get(_91UsernameCookieName)
104-
const encryptPassword = ctx.cookies.get(_91PwdCookieName)
105-
const password = decrypt(encryptPassword)
106-
return await getLcRequestData({
107-
[_91UsernameCookieName]: userName,
108-
[_91PwdCookieName]: password
109-
})
110-
}
111-
112104
async function submitSolution(problem, requestData){
113105
let statusCode = 403
114106
const url = submitUrl.replace('$slug', problem.slug);
@@ -128,7 +120,6 @@ async function submitSolution(problem, requestData){
128120
_delay: 1,// in seconds
129121
body: JSON.stringify(problem || {})
130122
}
131-
console.log(opt)
132123
const result = await fetch(url, opt).then((res) => {
133124
statusCode = res.status
134125
return res.json()
@@ -151,4 +142,50 @@ function formateSubmitData(problem = {}){
151142
})
152143
}
153144

145+
// 从leetcode的请求中获取cookie值
146+
function getCookieFromLc(resp, key) {
147+
const cookies = resp.headers['set-cookie'];
148+
if (!cookies) return null;
149+
150+
for (let i = 0; i < cookies.length; ++i) {
151+
const sections = cookies[i].split(';');
152+
for (let j = 0; j < sections.length; ++j) {
153+
const kv = sections[j].trim().split('=');
154+
if (kv[0] === key) return kv[1];
155+
}
156+
}
157+
return null;
158+
};
159+
160+
// 从leetcode中获取 发送请求的必要参数 LEETCODE_SESSION、csrftoken
161+
async function getLcRequestData(options){
162+
const opt = {
163+
url: loginUrl,
164+
credentials: 'include',
165+
headers: {
166+
credentials: 'include',
167+
Origin: baseUrl,
168+
Referer: loginUrl,
169+
},
170+
form: {
171+
[_91UsernameCookieName]: options[_91UsernameCookieName],
172+
[_91PwdCookieName]: options[_91PwdCookieName]
173+
}
174+
}
175+
return new Promise(resolve => {
176+
request.post(opt, function(e, resp, body) {
177+
if (resp.statusCode !== 302) {
178+
return resolve({success: false, message: 'pwd invaid'})
179+
}
180+
sessionId = getCookieFromLc(resp, lcSeesionCookieName);
181+
csrftoken = getCookieFromLc(resp, lcCsrftokenCookieName);
182+
resolve({
183+
success: true,
184+
[lcSeesionCookieName]: sessionId,
185+
[lcCsrftokenCookieName]:csrftoken
186+
})
187+
});
188+
})
189+
}
190+
154191
module.exports = router;

Diff for: routes/utils.js

-73
This file was deleted.

0 commit comments

Comments
 (0)