本文由 钟意 发布于:,更新于:

微信读书Cookies续活

机制分析

很多优秀的文章分析了延期机制, 这里列举两个

稳定性

目前跑了几天, Cookies都能自动刷新保活

每小时自动刷新回执
每小时自动刷新回执

主要代码

续活我没使用代理服务器, 直接请求了

refCookie
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 刷新 Cookie 的函数,模拟发送请求获取新 Cookie
const refCookie = async (uid: string) => {
try {
const response = await axios.head('https://weread.qq.com', { headers: globalHeaders() });
if (response.status === 200 || response.headers['set-cookie']) {
globalCookies = CookieUtil.WebArrayToString(response.headers['set-cookie'], globalCookies);
return (await upUserCookie(uid)) ? true : false
}else {
return false
}
} catch (e) {
return false
}
}

全部代码

运行在自己搭建的 Laf 云函数, 不能无脑抄。 代码虽烂 但已写注释。
需要临时使用我的接口可以联系我

代码结构图
这样也许清晰一点
这样也许清晰一点
Serverless Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
import axios from 'axios';
import cloud from "@/cloud-sdk";

/**
* API请求入口方法
*/
exports.main = async function (ctx: FunctionContext) {
try {
const { cookies, uid, refresh } = ctx.method === 'GET' ? ctx.query || ctx.params : ctx.body;
if (verifyData(uid)) { // 用户获取cookie请求
if ((await userServer.verifyUser(uid))) {
!(await CookiesApi.verifyRefresh(uid)) || (await CookiesApi.refCookie(refresh))
return msgServer.success("获取Cookie成功", { cookies: globalCookies })
} else {
return msgServer.failed("搞咩! " + uid + " 不存在!");
}
} else if (verifyData(cookies)) { // 新增用户请求
const uid = CookieUtil.StringToJson(cookies)['wr_vid']
globalCookies = cookies
const userInfo = (await CookiesApi.getUserInfo(uid))
if (!userInfo['name']) {
return msgServer.failed("搞咩! cookies 不能用!");
}
const userData: WxReadUser = {
'userVid': uid,
'userInfo': userInfo,
'cookies': globalCookies,
'cookies_uptime': (new Date()).valueOf(),
'cookies_life': true
}
const add = (await userServer.addUser(userData))
if (add.answer) {
return msgServer.success(
`存入cookies成功, 未来取用cookies请通过以下方式${'\n'}[ https://sijnzx.laf.thatcoder.cn/tencent-weread-refcookie?uid=您的userVid ]`,
{ userVid: uid, userInfo }
)
} else {
return msgServer.error()
}
} else if (verifyData(refresh)) { // 刷新请求
let req: any
if (!(await CookiesApi.verifyRefresh(refresh))) {
return msgServer.success("Cookie不需要刷新")
} else {
return (await CookiesApi.refCookie(refresh)) ? msgServer.success("刷新Cookie成功") : msgServer.error()
}
} else {
return msgServer.failed("搞咩! 传的什么狗屁参数!");
}
} catch (error) {
return msgServer.error()
}
};

/**
* 获取数据库访问器
*/
const db = cloud.database().collection('tc_tencent_wxread');

/**
* cookies格式工具
*/
const CookieUtil = {
StringToJson: (cookiesString: string) => {
const cookieGroup = cookiesString.split('; ')
const cookieJson = {}
for (let i = 0; i < cookieGroup.length; i++) {
const cookieGroupJson = cookieGroup[i].split('=')
cookieJson[cookieGroupJson[0]] = cookieGroupJson.length === 1 ? '' : cookieGroupJson[1]
}
return cookieJson
},
JsonToString: (cookiesJson: object) => {
const keyValuePairs = [];
for (const key in cookiesJson) {
if (cookiesJson.hasOwnProperty(key)) {
const value = cookiesJson[key];
keyValuePairs.push(`${key}=${value}`);
}
}
return keyValuePairs.join('; ');
},
WebArrayToString: (cookiesArray: Array<string>, cookiesString: string) => {
let cookieJson = CookieUtil.StringToJson(cookiesString)
for (const cookie of cookiesArray) {
const refresh: Array<string> = cookie.split('; ')[0].split('=')
cookieJson[refresh[0]] = refresh[1]
}
return CookieUtil.JsonToString(cookieJson)
},
StringToArray: (cookiesString: string) => {
return cookiesString.split('; ')
}
}

// 全局变量。不合理, 但是能减少云函数单文件代码量
var globalCookies = ""
var globalHeaders = () => {
return {
Cookie: CookieUtil.StringToArray(globalCookies), // 传入的 Cookie 数组
Referer: 'https://weread.qq.com/',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': '*',
}
}

/**
* 微信读书API方法
*/
const CookiesApi = {
/**
* 获取用户信息
* @uid: 微信Cookie['wr_vid']
*/
getUserInfo: async (uid: string) => {
let userInfo = { 'userVid': "" }
await axios.get('https://weread.qq.com/web/user?userVid=' + uid, { headers: globalHeaders() }).then(e => {
userInfo = e.data
})
return userInfo
},
/**
* 验证Cookie是否存活
* @uid: 微信Cookie['wr_vid']
*/
verifyAlive: async (uid: string) => {
const cookie = (await userServer.getUserCookie(uid))
globalCookies = cookie
let userInfo = await CookiesApi.getUserInfo(uid)
return (String)(userInfo['userVid']).includes(uid)
},
// 判断是否需要刷新 Cookie
verifyRefresh: async (uid: string) => {
const time = (await userServer.getUserCookieTime(uid))
if ( !(await CookiesApi.verifyAlive(uid)) || (new Date()).valueOf() - time >= 3600000) {
return true
}
return false
},
// 刷新 Cookie 的函数,模拟发送请求获取新 Cookie
refCookie: async (uid: string) => {
try {
const response = await axios.head('https://weread.qq.com', { headers: globalHeaders() });
// if (response.status === 200) {
// return true
// }
const newCookies = response.headers['set-cookie']
if (!newCookies) {
return false
}
globalCookies = CookieUtil.WebArrayToString(newCookies, globalCookies);
return (await userServer.upUserCookie(uid)) ? true : false
} catch (e) {
return false
}
}
}

/**
* 数据库服务层。 呵, JS哪来的服务层
*/
const userServer = {
/**
* 验证数据库是否存在用户
* @uid: 微信Cookie['wr_vid']
* @return: {boolean}
*/
verifyUser: async (uid: string) => {
return (await db.where({ 'userVid': uid }).count()).total > 0
},
/**
* 获取用户Cookie
* @uid: 微信Cookie['wr_vid']
*/
getUserCookie: async (uid: string) => {
const get = (await db.where({ 'userVid': uid }).limit(1).get())
return get.data[0]['cookies']
},
/**
* 获取用户CookieTime
* @uid: 微信Cookie['wr_vid']
*/
getUserCookieTime: async (uid: string) => {
const get = (await db.where({ 'userVid': uid }).limit(1).get())
return get.data[0]['cookies_uptime']
},
/**
* 更新用户Cookie
*/
upUserCookie: async (uid: string) => {
return (await db.where({'userVid': uid}).limit(1).update({ cookies: globalCookies, cookies_uptime: (new Date()).valueOf(), cookies_life: true })).ok
},
/**
* 新增数据库用户信息
*/
addUser: async (userData: WxReadUser) => {
let add: any
if ((await userServer.verifyUser(userData.userVid))) {
add = (await db.where({'userVid': userData.userVid}).limit(1).update(userData))
} else {
add = (await db.add(userData))
}
return { answer: add.ok, id: add.upsertId }
}
}

/**
* 回执服务层
*/
const msgServer = {
success: (msg: string, data: any = {}) => {
return JSON.stringify({ statusCode: 200, event: "操作成功", message: msg, data })
},
failed: (msg: string) => {
return JSON.stringify({ statusCode: 400, event: "操作失败", message: msg })
},
error: () => {
return JSON.stringify({ statusCode: 500, event: "程序错误", message: "请联系钟意, 必应搜索钟意博客。" })
}
}

/**
* 微信用户对象接口
*/
interface WxReadUser {
'userVid': string,
'userInfo'?: any,
'cookies': string,
'cookies_uptime'?: number,
'cookies_life'?: boolean
}

const verifyData = (data: any) => {
if (data === null || data === [] || data === {} || data === undefined || data === '') {
return false
} else if (data.length > 0) {
return true
} else {
return false
}
}

实际应用

  • 获取自己的微信读书信息
  • 下载微信读书的书籍
  • 导出书单信息
  • 带出读书笔记
  • 自动阅读( 这个功能有什么用? )

本站由 钟意 使用 Stellar 1.25.0 主题创建。
又拍云 提供CDN加速/云存储服务
vercel 提供托管服务
湘ICP备2023019799号-1
总访问 次 | 本页访问