Skip to content

Commit 022ab7e

Browse files
author
Hyseen
committed
添加[多看阅读]签到脚本
1 parent e9724ae commit 022ab7e

File tree

3 files changed

+298
-0
lines changed

3 files changed

+298
-0
lines changed

duokan/README.md

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# 多看阅读
2+
3+
> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可
4+
5+
> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight)
6+
7+
## 配置 (Surge)
8+
9+
```properties
10+
[MITM]
11+
www.duokan.com
12+
13+
[Script]
14+
http-request ^https:\/\/www\.duokan\.com\/checkin\/v0\/status script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.cookie.js, requires-body=true
15+
16+
cron "0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.js
17+
```
18+
19+
## 配置 (QuanX)
20+
21+
```properties
22+
[MITM]
23+
www.duokan.com
24+
25+
[rewrite_local]
26+
# [商店版] QuanX v1.0.6-build194 及更早版本
27+
^https:\/\/www\.duokan\.com\/checkin\/v0\/status url script-request-body duokan.cookie.js
28+
29+
# [TestFlight] QuanX v1.0.6-build195 及以后版本
30+
^https:\/\/www\.duokan\.com\/checkin\/v0\/status url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.cookie.js
31+
32+
[task_local]
33+
0 0 * * * duokan.js
34+
```
35+
36+
## 说明
37+
1. 先把 `www.duokan.com` 加到 `[MITM]`
38+
2. 再配置重写规则:
39+
- Surge: 把两条远程脚本放到 `[Script]`
40+
- QuanX: 把 `duokan.cookie.js``duokan.js` 传到 `On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关)
41+
3. 获取 Cookie: `我的` > `签到任务` 等到提示获取 Cookie 成功即可
42+
> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie.
43+
44+
> 第 2 条脚本是签到脚本, 每天 `00:00` 执行一次.
45+
46+
## 常见问题
47+
48+
1. 无法写入 Cookie
49+
50+
- 检查 Surge 系统通知权限放开了没
51+
- 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴)
52+
53+
2. 写入 Cookie 成功, 但签到不成功
54+
55+
- 看看是不是在登录前就写入 Cookie 了
56+
- 如果是,请确保在登录成功后,再尝试写入 Cookie
57+
58+
3. 为什么有时成功有时失败
59+
60+
- 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败)
61+
- 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学):
62+
63+
- `Surge`配置:
64+
65+
```properties
66+
# 没有什么是一顿饭解决不了的:
67+
cron "10 0 0 * * *" script-path=xxx.js # 每天 00:00:10 执行一次
68+
# 如果有,那就两顿:
69+
cron "20 0 0 * * *" script-path=xxx.js # 每天 00:00:20 执行一次
70+
# 实在不行,三顿也能接受:
71+
cron "30 0 0 * * *" script-path=xxx.js # 每天 00:00:30 执行一次
72+
73+
# 再粗暴点,直接:
74+
cron "* */60 * * * *" script-path=xxx.js # 每 60 分执行一次
75+
```
76+
77+
- `QuanX`配置:
78+
79+
```properties
80+
[task_local]
81+
1 0 * * * xxx.js # 每天 00:01 执行一次
82+
2 0 * * * xxx.js # 每天 00:02 执行一次
83+
3 0 * * * xxx.js # 每天 00:03 执行一次
84+
85+
*/60 * * * * xxx.js # 每 60 分执行一次
86+
```
87+
88+
## 感谢
89+
90+
[@NobyDa](https://github.com/NobyDa)
91+
92+
[@lhie1](https://github.com/lhie1)
93+
94+
[@ConnersHua](https://github.com/ConnersHua)

duokan/duokan.cookie.js

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
const DUOKAN_COOKIE_KEY = 'duokan_cookie'
2+
const DUOKAN_DEVICE_ID_KEY = 'duokan_device_id'
3+
4+
let $util = init()
5+
6+
if (typeof $request !== 'undefined') {
7+
getCookie()
8+
}
9+
$util.done({})
10+
11+
function getCookie() {
12+
let cookieVal = $request.headers['Cookie']
13+
$util.log(`cookie: ${cookieVal}`)
14+
if (cookieVal.indexOf('token=') !== -1 && cookieVal.indexOf('device_id=') !== -1) {
15+
let regexp = /device_id=(.*?);/g
16+
let matched = regexp.exec(cookieVal)
17+
if (matched) {
18+
let deviceId = matched[1]
19+
$util.log(`deviceId: ${deviceId}`)
20+
if ($util.setdata(cookieVal, DUOKAN_COOKIE_KEY) && $util.setdata(deviceId, DUOKAN_DEVICE_ID_KEY)) {
21+
$util.msg(`获取多看阅读 Cookie 成功 🎉`)
22+
}
23+
}
24+
}
25+
}
26+
27+
function init() {
28+
isSurge = () => {
29+
return undefined !== this.$httpClient
30+
}
31+
isQuanX = () => {
32+
return undefined !== this.$task
33+
}
34+
getdata = (key) => {
35+
if (isSurge()) return $persistentStore.read(key)
36+
if (isQuanX()) return $prefs.valueForKey(key)
37+
}
38+
setdata = (key, val) => {
39+
if (isSurge()) return $persistentStore.write(key, val)
40+
if (isQuanX()) return $prefs.setValueForKey(key, val)
41+
}
42+
msg = (title, subtitle = '', body = '') => {
43+
if (isSurge()) $notification.post(title, subtitle, body)
44+
if (isQuanX()) $notify(title, subtitle, body)
45+
}
46+
log = (msg) => {
47+
console.log(`${msg}\n`)
48+
}
49+
get = (options, callback) => {
50+
if (isQuanX()) {
51+
if (typeof options == 'string') options = { url: options }
52+
options['method'] = 'GET'
53+
return $task.fetch(options).then(
54+
(response) => {
55+
response['status'] = response.statusCode
56+
callback(null, response, response.body)
57+
},
58+
(reason) => callback(reason.error, null, null)
59+
)
60+
}
61+
if (isSurge()) return $httpClient.get(options, callback)
62+
}
63+
post = (options, callback) => {
64+
if (isQuanX()) {
65+
if (typeof options == 'string') options = { url: options }
66+
options['method'] = 'POST'
67+
$task.fetch(options).then(
68+
(response) => {
69+
response['status'] = response.statusCode
70+
callback(null, response, response.body)
71+
},
72+
(reason) => callback(reason.error, null, null)
73+
)
74+
}
75+
if (isSurge()) $httpClient.post(options, callback)
76+
}
77+
done = (value = {}) => {
78+
$done(value)
79+
}
80+
return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done }
81+
}

duokan/duokan.js

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
const DUOKAN_COOKIE_KEY = 'duokan_cookie'
2+
const DUOKAN_DEVICE_ID_KEY = 'duokan_device_id'
3+
const API_HOST = 'https://www.duokan.com'
4+
const TASK_NAME = '多看阅读'
5+
6+
let $util = init()
7+
8+
;(async () => {
9+
let cookieVal = $util.getdata(DUOKAN_COOKIE_KEY)
10+
let deviceId = $util.getdata(DUOKAN_DEVICE_ID_KEY)
11+
if (!cookieVal || !deviceId) {
12+
$util.msg(TASK_NAME, '⚠️ 请先获取 Cookie')
13+
$util.done({})
14+
return
15+
}
16+
await checkin(cookieVal, deviceId).then(() => {
17+
$util.done({})
18+
})
19+
})()
20+
21+
function checkin(cookieVal, deviceId) {
22+
return new Promise((resolve, reject) => {
23+
let options = {
24+
url: `${API_HOST}/checkin/v0/checkin`,
25+
headers: {
26+
'User-Agent':
27+
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
28+
Cookie: cookieVal
29+
},
30+
body: signature(deviceId)
31+
}
32+
$util.post(options, (error, response, data) => {
33+
if (error) {
34+
$util.log(`签到失败,error:${error}`)
35+
$util.msg(TASK_NAME, '⚠️ 签到失败,详情请查看日志')
36+
resolve()
37+
return
38+
}
39+
let result = JSON.parse(data)
40+
if (result && result.result === 0 && result.data) {
41+
$util.log(`签到成功,response: ${data}`)
42+
let subtitle = `签到成功,已连续签到 ${result.data.today} 天`
43+
let body = ''
44+
if (result.data.gift && Array.isArray(result.data.gift) && result.data.gift.length > 0) {
45+
body = result.data.gift.reduce((prev, cur) => {
46+
return (prev += `获得 ${cur.value}${cur.name} \n`)
47+
}, '')
48+
}
49+
$util.msg(TASK_NAME, subtitle, body)
50+
resolve()
51+
} else {
52+
$util.log(`签到失败,response: ${data}`)
53+
$util.msg(TASK_NAME, `⚠️ 签到失败,${result.msg}`)
54+
resolve()
55+
}
56+
})
57+
})
58+
}
59+
60+
function signature(deviceId) {
61+
let t = parseInt(new Date().getTime() / 1000)
62+
let c = 0
63+
for (char of `${deviceId}&${t}`) {
64+
c = (c * 131 + char.charCodeAt(0)) % 65536
65+
}
66+
return `_t=${t}&_c=${c}`
67+
}
68+
69+
function init() {
70+
isSurge = () => {
71+
return undefined !== this.$httpClient
72+
}
73+
isQuanX = () => {
74+
return undefined !== this.$task
75+
}
76+
getdata = (key) => {
77+
if (isSurge()) return $persistentStore.read(key)
78+
if (isQuanX()) return $prefs.valueForKey(key)
79+
}
80+
setdata = (key, val) => {
81+
if (isSurge()) return $persistentStore.write(key, val)
82+
if (isQuanX()) return $prefs.setValueForKey(key, val)
83+
}
84+
msg = (title, subtitle = '', body = '') => {
85+
if (isSurge()) $notification.post(title, subtitle, body)
86+
if (isQuanX()) $notify(title, subtitle, body)
87+
}
88+
log = (msg) => {
89+
console.log(`${msg}\n`)
90+
}
91+
get = (options, callback) => {
92+
if (isQuanX()) {
93+
if (typeof options == 'string') options = { url: options }
94+
options['method'] = 'GET'
95+
return $task.fetch(options).then(
96+
(response) => {
97+
response['status'] = response.statusCode
98+
callback(null, response, response.body)
99+
},
100+
(reason) => callback(reason.error, null, null)
101+
)
102+
}
103+
if (isSurge()) return $httpClient.get(options, callback)
104+
}
105+
post = (options, callback) => {
106+
if (isQuanX()) {
107+
if (typeof options == 'string') options = { url: options }
108+
options['method'] = 'POST'
109+
$task.fetch(options).then(
110+
(response) => {
111+
response['status'] = response.statusCode
112+
callback(null, response, response.body)
113+
},
114+
(reason) => callback(reason.error, null, null)
115+
)
116+
}
117+
if (isSurge()) $httpClient.post(options, callback)
118+
}
119+
done = (value = {}) => {
120+
$done(value)
121+
}
122+
return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done }
123+
}

0 commit comments

Comments
 (0)