@skills-store/rednote 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/rednote/login.js +76 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -333,6 +333,7 @@ Use these shapes as the success model when a command returns JSON.
|
|
|
333
333
|
"loginClicked": true,
|
|
334
334
|
"pageUrl": "string",
|
|
335
335
|
"waitingForPhoneLogin": true,
|
|
336
|
+
"qrCodePath": "string|null",
|
|
336
337
|
"message": "string"
|
|
337
338
|
}
|
|
338
339
|
}
|
|
@@ -490,7 +491,7 @@ If a command fails, check these in order:
|
|
|
490
491
|
|
|
491
492
|
## Repository
|
|
492
493
|
|
|
493
|
-
- Homepage: https://github.com/skills-router/skills-store/tree/main/packages/rednote
|
|
494
|
+
- Homepage: https://github.com/skills-router/skills-store/tree/main/packages/rednote-cli
|
|
494
495
|
- Issues: https://github.com/skills-router/skills-store/issues
|
|
495
496
|
|
|
496
497
|
## License
|
package/dist/rednote/login.js
CHANGED
|
@@ -1,8 +1,79 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
2
4
|
import { parseArgs } from 'node:util';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
3
6
|
import { printJson, runCli } from '../utils/browser-cli.js';
|
|
4
7
|
import { resolveStatusTarget } from './status.js';
|
|
5
8
|
import { checkRednoteLogin, createRednoteSession, disconnectRednoteSession } from './checkLogin.js';
|
|
9
|
+
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const REDNOTE_ROOT = path.resolve(SCRIPT_DIR, '../..');
|
|
11
|
+
function timestampForFilename() {
|
|
12
|
+
return new Date().toISOString().replaceAll(':', '').replaceAll('.', '').replace('T', '-').replace('Z', 'Z');
|
|
13
|
+
}
|
|
14
|
+
function resolveQrCodePath() {
|
|
15
|
+
return path.join(REDNOTE_ROOT, 'output', `login-qrcode-${timestampForFilename()}.png`);
|
|
16
|
+
}
|
|
17
|
+
function parseQrCodeDataUrl(src) {
|
|
18
|
+
const match = src.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$/);
|
|
19
|
+
if (!match) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
mimeType: match[1],
|
|
24
|
+
buffer: Buffer.from(match[2], 'base64')
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function refreshExpiredQrCode(page) {
|
|
28
|
+
const statusText = page.locator('.qrcode .status-text').first();
|
|
29
|
+
const refreshButton = page.locator('.qrcode .status-desc.refresh').first();
|
|
30
|
+
const isExpiredVisible = await statusText.isVisible().catch(()=>false);
|
|
31
|
+
if (!isExpiredVisible) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const text = (await statusText.textContent().catch(()=>null))?.trim() ?? '';
|
|
35
|
+
if (!text.includes('过期')) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (await refreshButton.isVisible().catch(()=>false)) {
|
|
39
|
+
await refreshButton.click({
|
|
40
|
+
timeout: 2_000
|
|
41
|
+
}).catch(()=>{});
|
|
42
|
+
await page.waitForTimeout(800);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
async function saveQrCodeImage(page) {
|
|
48
|
+
const qrImage = page.locator('.qrcode .qrcode-img').first();
|
|
49
|
+
for(let attempt = 0; attempt < 3; attempt += 1){
|
|
50
|
+
await qrImage.waitFor({
|
|
51
|
+
state: 'visible',
|
|
52
|
+
timeout: 5_000
|
|
53
|
+
});
|
|
54
|
+
const refreshed = await refreshExpiredQrCode(page);
|
|
55
|
+
if (refreshed) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const filePath = resolveQrCodePath();
|
|
59
|
+
fs.mkdirSync(path.dirname(filePath), {
|
|
60
|
+
recursive: true
|
|
61
|
+
});
|
|
62
|
+
const src = await qrImage.getAttribute('src');
|
|
63
|
+
if (src) {
|
|
64
|
+
const parsed = parseQrCodeDataUrl(src);
|
|
65
|
+
if (parsed?.mimeType === 'image/png') {
|
|
66
|
+
fs.writeFileSync(filePath, parsed.buffer);
|
|
67
|
+
return filePath;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
await qrImage.screenshot({
|
|
71
|
+
path: filePath
|
|
72
|
+
});
|
|
73
|
+
return filePath;
|
|
74
|
+
}
|
|
75
|
+
throw new Error('未检测到可用的小红书登录二维码,请确认登录弹窗是否已打开。');
|
|
76
|
+
}
|
|
6
77
|
function printLoginHelp() {
|
|
7
78
|
process.stdout.write(`rednote login
|
|
8
79
|
|
|
@@ -36,6 +107,7 @@ export async function openRednoteLogin(target, session) {
|
|
|
36
107
|
loginClicked: false,
|
|
37
108
|
pageUrl: session.page.url(),
|
|
38
109
|
waitingForPhoneLogin: false,
|
|
110
|
+
qrCodePath: null,
|
|
39
111
|
message: '当前实例已登录,无需重复执行登录操作。'
|
|
40
112
|
}
|
|
41
113
|
};
|
|
@@ -50,6 +122,7 @@ export async function openRednoteLogin(target, session) {
|
|
|
50
122
|
loginClicked: false,
|
|
51
123
|
pageUrl: page.url(),
|
|
52
124
|
waitingForPhoneLogin: false,
|
|
125
|
+
qrCodePath: null,
|
|
53
126
|
message: '未检测到登录按钮,当前实例可能已经登录。'
|
|
54
127
|
}
|
|
55
128
|
};
|
|
@@ -58,13 +131,15 @@ export async function openRednoteLogin(target, session) {
|
|
|
58
131
|
timeout: 2000
|
|
59
132
|
});
|
|
60
133
|
await page.waitForTimeout(500);
|
|
134
|
+
const qrCodePath = await saveQrCodeImage(page);
|
|
61
135
|
return {
|
|
62
136
|
ok: true,
|
|
63
137
|
rednote: {
|
|
64
138
|
loginClicked: true,
|
|
65
139
|
pageUrl: page.url(),
|
|
66
140
|
waitingForPhoneLogin: true,
|
|
67
|
-
|
|
141
|
+
qrCodePath,
|
|
142
|
+
message: '已点击登录按钮并导出二维码图片,请扫码完成登录。'
|
|
68
143
|
}
|
|
69
144
|
};
|
|
70
145
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skills-store/rednote",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"repository": {
|
|
51
51
|
"type": "git",
|
|
52
52
|
"url": "git+https://github.com/skills-router/skills-store.git",
|
|
53
|
-
"directory": "packages/rednote"
|
|
53
|
+
"directory": "packages/rednote-cli"
|
|
54
54
|
},
|
|
55
|
-
"homepage": "https://github.com/skills-router/skills-store/tree/main/packages/rednote",
|
|
55
|
+
"homepage": "https://github.com/skills-router/skills-store/tree/main/packages/rednote-cli",
|
|
56
56
|
"bugs": {
|
|
57
57
|
"url": "https://github.com/skills-router/skills-store/issues"
|
|
58
58
|
},
|