Skip to content

Commit f021ae7

Browse files
BrandonStudioCopilotPIKACHUIM
authored
feat(driver): Add 115 QR Code (#76)
* Add 115 QR Code - Refactor QR Code - Update dev method - Update dependencies (see PR description for details) * Remove argument from refreshQRCode I forget why it appears. Hopefully this patch is correct Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: BrandonStudio <55647556+BrandonStudio@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com> * Update src/driver/115cloud_qr.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com> * Update public/static/115qr.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com> --------- Signed-off-by: BrandonStudio <55647556+BrandonStudio@users.noreply.github.com> Signed-off-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
1 parent 6ef91ef commit f021ae7

10 files changed

Lines changed: 709 additions & 112 deletions

File tree

package-lock.json

Lines changed: 455 additions & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cf-worker-api",
33
"scripts": {
4-
"dev-js": "tsx watch src/basic.ts",
4+
"dev-js": "tsx watch --include \"public/**\" src/basic.ts",
55
"build-js": "webpack --mode production",
66
"deploy-js": "node dist/bundle.js",
77
"dev-cf": "wrangler dev",

public/index.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ <h2 class="text-center mb-4">🔐 OpenList Token 获取工具</h2>
3333
<option value="baiduyun_ob">百度网盘 (OAuth2) 手动登录</option>
3434
<option value="quarkyun_fn">夸克网盘 (OAuth2) 验证登录</option>
3535
<option value="115cloud_go">115 网盘 (OAuth2) 跳转登录</option>
36+
<option value="115cloud_qr">115 网盘 扫码</option>
3637
<option value="123cloud_go">123 网盘 (OAuth2) 跳转登录</option>
3738
<option value="dropboxs_go">Drop Box (OAuth2) 跳转登录</option>
3839
<option value="googleui_go">GoogleDrive Login (OAuth2)</option>
@@ -133,12 +134,15 @@ <h2 class="text-center mb-4">🔐 OpenList Token 获取工具</h2>
133134
<div id="qr-modal" class="qr-modal">
134135
<div class="qr-modal-content">
135136
<span class="close-btn" onclick="closeQRModal()">&times;</span>
136-
<h4>阿里云盘扫码登录v2</h4>
137+
<h4 id="qr-modal-title"></h4>
137138
<div id="qr-code-container" class="qr-code-container" style="display: none;">
138139
<div id="qr-code-display"></div>
139140
</div>
140141
<div id="qr-status" class="qr-status" style="display: none;"></div>
141142
<div class="mt-3">
143+
<button id="qr-status-btn" class="btn btn-secondary" onclick="checkQRStatus()">
144+
刷新状态
145+
</button>
142146
<button id="refresh-qr-btn" class="btn btn-secondary" onclick="refreshQRCode()" style="display: none;">
143147
刷新二维码
144148
</button>
@@ -171,7 +175,9 @@ <h4>隐私政策和使用条款</h4>
171175
<script src="/static/login.js"></script>
172176
<script src="/static/token.js"></script>
173177
<script src="/static/theme.js"></script>
178+
<script src="/static/qr.js"></script>
174179
<script src="/static/aliv2.js"></script>
180+
<script src="/static/115qr.js"></script>
175181
<script src="/static/eulas.js"></script>
176182
<script src="/static/spoid.js"></script>
177183
<script src="/static/input.js"></script>

public/static/115qr.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* @typedef {import('../../src/driver/115cloud_qr.ts').QRCodeResponse} QRCodeResponse
3+
*/
4+
5+
async function start115CloudQRLogin() {
6+
try {
7+
// 显示模态框
8+
document.getElementById('qr-modal').style.display = 'block';
9+
setQRStatus('正在生成二维码...', 'waiting');
10+
11+
// 生成二维码 - 向后端发送请求
12+
const response = await fetch(`/115cloud_qr/get_qr`);
13+
if (response.ok) {
14+
/** @type {QRCodeResponse} */
15+
const result = await response.json();
16+
showQRCode(result.qrcode);
17+
18+
setQRStatus('请使用115 App扫描二维码', 'waiting');
19+
20+
checkQRStatus = () => check115CloudQRStatus(result);
21+
22+
// qr115CheckInterval = setInterval(() => check115CloudQRStatus(result), 2000);
23+
} else {
24+
setQRStatus(response.statusText || '生成二维码失败', 'error');
25+
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
26+
}
27+
} catch (error) {
28+
setQRStatus('网络错误,请重试', 'error');
29+
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
30+
console.error('生成二维码失败:', error);
31+
}
32+
}
33+
34+
/**
35+
* @param {QRCodeResponse} body
36+
*/
37+
async function check115CloudQRStatus(body) {
38+
try {
39+
const response = await fetch('/115cloud_qr/check_status', {
40+
method: 'POST',
41+
headers: {
42+
'Content-Type': 'application/json'
43+
},
44+
body: JSON.stringify(body),
45+
});
46+
/** @type {HTMLButtonElement} */
47+
const refreshBtn = document.getElementById('refresh-qr-btn');
48+
if (response.ok) {
49+
const status = await response.text();
50+
switch (status) {
51+
case '0':
52+
setQRStatus('等待扫描二维码', 'waiting');
53+
break;
54+
case '1':
55+
setQRStatus('二维码已扫描,请在手机上确认登录', 'waiting');
56+
break;
57+
case '2':
58+
setQRStatus('登录成功', 'success');
59+
// clearInterval(qr115CheckInterval);
60+
document.getElementById("access-token").value = body.uid;
61+
closeQRModal();
62+
break;
63+
case '-1':
64+
setQRStatus('二维码已过期,请刷新重试', 'error');
65+
refreshBtn.style.display = 'inline-block';
66+
break;
67+
case '-2':
68+
setQRStatus('登录已取消,请重试', 'error');
69+
refreshBtn.style.display = 'inline-block';
70+
break;
71+
default:
72+
setQRStatus(`未知状态: ${status}`, 'info');
73+
}
74+
} else {
75+
setQRStatus('检查登录状态失败', 'error');
76+
}
77+
} catch (error) {
78+
setQRStatus('网络错误,请重试', 'error');
79+
console.error('检查登录状态失败:', error);
80+
}
81+
}

public/static/aliv2.js

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ async function startAlicloud2Login() {
6868
// console.log(`会话将在 ${expireMinutes} 分钟后过期`);
6969
}
7070

71-
startStatusCheck();
71+
checkQRStatus = checkAlicloud2Status;
72+
startAliQRStatusCheck();
7273
} else {
7374
setQRStatus(result.error || '生成二维码失败', 'error');
7475
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
@@ -80,29 +81,14 @@ async function startAlicloud2Login() {
8081
}
8182
}
8283

83-
// 显示二维码
84-
function showQRCode(qrUrl) {
85-
const qrApiUrl = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrUrl)}`;
86-
document.getElementById('qr-code-display').innerHTML = `<img src="${qrApiUrl}" alt="二维码" class="qr-code-img">`;
87-
document.getElementById('qr-code-container').style.display = 'block';
88-
}
89-
90-
// 设置状态
91-
function setQRStatus(message, type) {
92-
const statusEl = document.getElementById('qr-status');
93-
statusEl.textContent = message;
94-
statusEl.className = `qr-status ${type}`;
95-
statusEl.style.display = 'block';
96-
}
97-
9884
// 开始状态检查
99-
function startStatusCheck() {
100-
stopStatusCheck();
85+
function startAliQRStatusCheck() {
86+
stopAliQRStatusCheck();
10187
alicloud2CheckInterval = setInterval(checkAlicloud2Status, 2000);
10288
}
10389

10490
// 停止状态检查
105-
function stopStatusCheck() {
91+
function stopAliQRStatusCheck() {
10692
if (alicloud2CheckInterval) {
10793
clearInterval(alicloud2CheckInterval);
10894
alicloud2CheckInterval = null;
@@ -118,7 +104,7 @@ async function checkAlicloud2Status() {
118104
if (elapsed > 180000) { // 3分钟
119105
setQRStatus('二维码可能已过期,建议点击刷新重新生成', 'error');
120106
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
121-
stopStatusCheck();
107+
stopAliQRStatusCheck();
122108
return;
123109
}
124110

@@ -138,15 +124,15 @@ async function checkAlicloud2Status() {
138124
break;
139125
case 'CONFIRMED':
140126
setQRStatus('登录成功!正在获取用户信息...', 'success');
141-
stopStatusCheck();
127+
stopAliQRStatusCheck();
142128
// 稍等一下确保token已保存
143129
setTimeout(async () => {
144130
await getAlicloud2UserInfo();
145131
}, 1000);
146132
break;
147133
case 'EXPIRED':
148134
setQRStatus('二维码已过期,请点击刷新重新生成', 'error');
149-
stopStatusCheck();
135+
stopAliQRStatusCheck();
150136
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
151137
break;
152138
}
@@ -155,7 +141,7 @@ async function checkAlicloud2Status() {
155141
if (response.status === 403) {
156142
setQRStatus('会话验证失败,请重新生成二维码', 'error');
157143
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
158-
stopStatusCheck();
144+
stopAliQRStatusCheck();
159145
} else {
160146
setQRStatus('检查状态失败: ' + (result.error || '未知错误'), 'error');
161147
document.getElementById('refresh-qr-btn').style.display = 'inline-block';
@@ -215,35 +201,3 @@ async function getAlicloud2UserInfo() {
215201
}
216202
}
217203

218-
// 刷新二维码
219-
async function refreshQRCode() {
220-
document.getElementById('refresh-qr-btn').style.display = 'none';
221-
// 清理旧会话
222-
if (alicloud2SessionId) {
223-
try {
224-
await fetchWithFingerprint(`/alicloud2/logout?session_id=${alicloud2SessionId}`);
225-
} catch (e) {
226-
// console.log('清理旧会话失败:', e);
227-
}
228-
alicloud2SessionId = null;
229-
}
230-
await startAlicloud2Login();
231-
}
232-
233-
// 关闭模态框
234-
function closeQRModal() {
235-
document.getElementById('qr-modal').style.display = 'none';
236-
stopStatusCheck();
237-
238-
// 清理会话
239-
if (alicloud2SessionId) {
240-
fetchWithFingerprint(`/alicloud2/logout?session_id=${alicloud2SessionId}`);
241-
alicloud2SessionId = null;
242-
}
243-
244-
// 重置界面
245-
document.getElementById('qr-code-container').style.display = 'none';
246-
document.getElementById('qr-status').style.display = 'none';
247-
document.getElementById('refresh-qr-btn').style.display = 'none';
248-
}
249-

public/static/event.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@ function onSelect() {
3434
// 阿里云盘扫码登录v2不需要客户端ID、应用机密和回调地址 ================
3535
if (driver_txt_input.value === "alicloud_cs"
3636
|| driver_txt_input.value === "alicloud_tv"
37+
|| driver_txt_input.value === "115cloud_qr"
3738
) {
3839
// 隐藏整个字段容器
3940
clientIdContainer.style.display = 'none';
4041
appSecretContainer.style.display = 'none';
4142
serverUseContainer.style.display = 'none';
4243
callbackContainer.style.display = 'none';
44+
// 这些驱动使用服务器端配置,强制启用 server_use
4345
server_use_input.checked = true;
4446
} else {
4547
clientIdContainer.style.display = 'block';

public/static/login.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
// import Swal from 'sweetalert2';
22

3+
/** @type {string | undefined} */
4+
var driver_txt;
5+
36
// 获取登录秘钥 #######################################################
47
async function getLogin(refresh = false) {
58
let server_use = document.getElementById("server-use-input").checked;
69
let secret_key = document.getElementById("secret-key-input").value;
710
let client_uid = document.getElementById("client-uid-input").value;
811
let client_key = document.getElementById("client-key-input").value;
9-
let driver_txt = document.getElementById("driver-txt-input").value;
12+
driver_txt = document.getElementById("driver-txt-input").value;
1013
let refresh_ui = document.getElementById("refresh-token").value;
14+
/** @type {HTMLHeadingElement} */
15+
const qrModalTitle = document.getElementById('qr-modal-title');
1116
let driver_pre = driver_txt.split("_")[0]
1217
let check_flag = true;
18+
// 阿里云盘扫码v2直接调用专用API,不需要构建传统的requests路径
19+
if (driver_txt === "alicloud_cs" && !refresh) {
20+
qrModalTitle.textContent = '阿里云盘扫码登录v2';
21+
await startAlicloud2Login();
22+
return;
23+
} else if (driver_txt === "115cloud_qr") {
24+
// Ignore refresh
25+
qrModalTitle.textContent = '115网盘扫码登录';
26+
await start115CloudQRLogin();
27+
return;
28+
}
1329
// 验证秘钥情况 ==================================================
1430
if (!server_use) {
1531
if (driver_txt !== "alicloud_cs"
@@ -26,11 +42,6 @@ async function getLogin(refresh = false) {
2642
return;
2743
}
2844
}
29-
// 阿里云盘扫码v2直接调用专用API,不需要构建传统的requests路径
30-
if (driver_txt === "alicloud_cs" && !refresh) {
31-
await startAlicloud2Login();
32-
return;
33-
}
3445
// 刷新秘钥情况 =================================================
3546
let base_urls = "/requests?client_uid="
3647
if (refresh) {

public/static/qr.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// 显示二维码
2+
function showQRCode(qrUrl) {
3+
const qrApiUrl = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrUrl)}`;
4+
document.getElementById('qr-code-display').innerHTML = `<img src="${qrApiUrl}" alt="二维码" class="qr-code-img">`;
5+
document.getElementById('qr-code-container').style.display = 'block';
6+
}
7+
8+
// 设置状态
9+
function setQRStatus(message, type) {
10+
const statusEl = document.getElementById('qr-status');
11+
statusEl.textContent = message;
12+
statusEl.className = `qr-status ${type}`;
13+
statusEl.style.display = 'block';
14+
}
15+
16+
/** @type {() => Promise<void> | null} */
17+
var checkQRStatus = null;
18+
19+
/**
20+
* @summary 刷新二维码
21+
*/
22+
async function refreshQRCode() {
23+
document.getElementById('refresh-qr-btn').style.display = 'none';
24+
// 清理旧会话
25+
switch (driver_txt) {
26+
case 'alicloud_cs':
27+
if (alicloud2SessionId) {
28+
try {
29+
await fetchWithFingerprint(`/alicloud2/logout?session_id=${alicloud2SessionId}`);
30+
} catch (e) {
31+
// console.log('清理旧会话失败:', e);
32+
}
33+
alicloud2SessionId = null;
34+
}
35+
await startAlicloud2Login();
36+
break;
37+
case '115cloud_qr':
38+
await start115CloudQRLogin();
39+
break;
40+
}
41+
}
42+
43+
// 关闭模态框
44+
function closeQRModal() {
45+
document.getElementById('qr-modal').style.display = 'none';
46+
switch (driver_txt) {
47+
case 'alicloud_cs':
48+
stopAliQRStatusCheck();
49+
50+
// 清理会话
51+
if (alicloud2SessionId) {
52+
fetchWithFingerprint(`/alicloud2/logout?session_id=${alicloud2SessionId}`);
53+
alicloud2SessionId = null;
54+
}
55+
break;
56+
case '115cloud_qr':
57+
58+
break;
59+
}
60+
61+
// 重置界面
62+
document.getElementById('qr-code-container').style.display = 'none';
63+
document.getElementById('qr-status').style.display = 'none';
64+
document.getElementById('refresh-qr-btn').style.display = 'none';
65+
}
66+

0 commit comments

Comments
 (0)