@lightcone-ai/daemon 0.9.65 → 0.9.66
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.
|
@@ -24,6 +24,7 @@ const REQUIREMENTS = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish';
|
|
27
|
+
const IMAGE_PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish?target=image';
|
|
27
28
|
const VIDEO_PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish?source=video';
|
|
28
29
|
|
|
29
30
|
const CREATOR_HOME_URL = 'https://creator.xiaohongshu.com/new/home';
|
|
@@ -135,13 +136,21 @@ export class XhsAdapter {
|
|
|
135
136
|
async _openPublishComposer(kind) {
|
|
136
137
|
const targetTabText = kind === 'image' ? '上传图文' : '上传视频';
|
|
137
138
|
const inputSelector = kind === 'image' ? IMAGE_FILE_INPUT_SELECTOR : VIDEO_FILE_INPUT_SELECTOR;
|
|
138
|
-
const url = kind === 'video' ? VIDEO_PUBLISH_URL :
|
|
139
|
+
const url = kind === 'video' ? VIDEO_PUBLISH_URL : IMAGE_PUBLISH_URL;
|
|
139
140
|
|
|
140
141
|
await this._cdp.send('Page.navigate', { url });
|
|
141
142
|
await this._waitForCreatorShell(20_000);
|
|
142
143
|
await this._assertReadyForPublish();
|
|
143
144
|
|
|
144
|
-
await this.
|
|
145
|
+
if (await this._hasSelector(inputSelector)) return;
|
|
146
|
+
|
|
147
|
+
const clicked = await this._clickVisibleByText(targetTabText, '.creator-tab, button, [role="button"], span, div', { throwOnMissing: false });
|
|
148
|
+
if (clicked) {
|
|
149
|
+
await this._waitForAny([inputSelector], 15_000);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
await this._cdp.send('Page.navigate', { url: kind === 'image' ? `${PUBLISH_URL}?from=tab_switch&target=image` : VIDEO_PUBLISH_URL });
|
|
145
154
|
await this._waitForAny([inputSelector], 15_000);
|
|
146
155
|
}
|
|
147
156
|
|
|
@@ -186,6 +195,14 @@ export class XhsAdapter {
|
|
|
186
195
|
throw new Error(`Timeout waiting for any of: ${combined}`);
|
|
187
196
|
}
|
|
188
197
|
|
|
198
|
+
async _hasSelector(selector) {
|
|
199
|
+
const result = await this._cdp.send('Runtime.evaluate', {
|
|
200
|
+
expression: `!!document.querySelector(${JSON.stringify(selector)})`,
|
|
201
|
+
returnByValue: true,
|
|
202
|
+
});
|
|
203
|
+
return result.result?.value === true;
|
|
204
|
+
}
|
|
205
|
+
|
|
189
206
|
async _waitForText(text, timeoutMs = 8000) {
|
|
190
207
|
const deadline = Date.now() + timeoutMs;
|
|
191
208
|
while (Date.now() < deadline) {
|
|
@@ -364,7 +381,7 @@ export class XhsAdapter {
|
|
|
364
381
|
await sleep(500);
|
|
365
382
|
}
|
|
366
383
|
|
|
367
|
-
async _clickVisibleByText(text, selector) {
|
|
384
|
+
async _clickVisibleByText(text, selector, { throwOnMissing = true } = {}) {
|
|
368
385
|
const result = await this._cdp.send('Runtime.evaluate', {
|
|
369
386
|
expression: `
|
|
370
387
|
(function() {
|
|
@@ -374,7 +391,11 @@ export class XhsAdapter {
|
|
|
374
391
|
return r.width > 0 && r.height > 0 && r.left > -100 && s.display !== 'none' && s.visibility !== 'hidden';
|
|
375
392
|
};
|
|
376
393
|
const els = [...document.querySelectorAll(${JSON.stringify(selector)})].filter(visible);
|
|
377
|
-
const
|
|
394
|
+
const targetText = ${JSON.stringify(text)};
|
|
395
|
+
const el = els.find(e => {
|
|
396
|
+
const t = (e.innerText || e.textContent || '').trim();
|
|
397
|
+
return t === targetText || t.split(/\\s+/).includes(targetText) || t.includes(targetText);
|
|
398
|
+
});
|
|
378
399
|
const target = el?.closest('.creator-tab, button, [role="button"]') || el;
|
|
379
400
|
if (target) { target.click(); return true; }
|
|
380
401
|
return false;
|
|
@@ -382,8 +403,10 @@ export class XhsAdapter {
|
|
|
382
403
|
`,
|
|
383
404
|
returnByValue: true,
|
|
384
405
|
});
|
|
385
|
-
|
|
386
|
-
|
|
406
|
+
const clicked = result.result?.value === true;
|
|
407
|
+
if (!clicked && throwOnMissing) throw new Error(`PUBLISH_FAILED: 找不到小红书发布入口:${text}`);
|
|
408
|
+
if (clicked) await sleep(1000);
|
|
409
|
+
return clicked;
|
|
387
410
|
}
|
|
388
411
|
|
|
389
412
|
async _clickByText(text) {
|