channel-worker 2.5.8 → 2.5.10
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/package.json +1 -1
- package/scripts/upload_facebook.js +40 -9
package/package.json
CHANGED
|
@@ -128,22 +128,40 @@ async function dumpFailure(page, tag, log) {
|
|
|
128
128
|
// "Đã hiểu" / "Bỏ qua" inside the dialog, then check again.
|
|
129
129
|
async function dismissBsOnboarding(page, log) {
|
|
130
130
|
for (let pass = 0; pass < 3; pass++) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
// Pick the FIRST visible dialog that is NOT the Reels composer. The
|
|
132
|
+
// Reels modal ('Tạo thước phim' / 'Create reel') has its own '✕' Close
|
|
133
|
+
// button with aria-label='Đóng'; without this guard dismissBsOnboarding
|
|
134
|
+
// happily closes the composer immediately after we just opened it, and
|
|
135
|
+
// the subsequent 'Thêm video' click can't find the modal.
|
|
136
|
+
const dlgInfo = await page.evaluate(() => {
|
|
137
|
+
const dlgs = document.querySelectorAll("[role='dialog']");
|
|
138
|
+
for (const d of dlgs) {
|
|
139
|
+
const r = d.getBoundingClientRect();
|
|
140
|
+
if (r.width < 8 || r.height < 8) continue;
|
|
141
|
+
const cs = getComputedStyle(d);
|
|
142
|
+
if (cs.visibility === 'hidden' || cs.display === 'none') continue;
|
|
143
|
+
const txt = (d.innerText || '').slice(0, 400);
|
|
144
|
+
// Skip the Reels composer — that's the modal we just opened.
|
|
145
|
+
if (/Tạo thước phim|Create reel|Create a reel|Tạo thư�?c phim/i.test(txt)) continue;
|
|
146
|
+
d.setAttribute('__fbpw_onboarding__', '1');
|
|
147
|
+
return { tag: 'ok', preview: txt.slice(0, 80) };
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}).catch(() => null);
|
|
151
|
+
if (!dlgInfo) return;
|
|
134
152
|
const phrases = ['Đã hiểu', 'Got it', 'Bỏ qua', 'Skip', 'Để sau', 'Not now', 'Đóng', 'Close', 'Tiếp tục', 'Continue'];
|
|
135
153
|
let clicked = false;
|
|
136
154
|
for (const p of phrases) {
|
|
137
155
|
const candidates = [
|
|
138
|
-
`[
|
|
139
|
-
`[
|
|
140
|
-
`[
|
|
156
|
+
`[__fbpw_onboarding__='1'] [aria-label*='${p}']`,
|
|
157
|
+
`[__fbpw_onboarding__='1'] [role='button']:has-text('${p}')`,
|
|
158
|
+
`[__fbpw_onboarding__='1'] button:has-text('${p}')`,
|
|
141
159
|
];
|
|
142
160
|
for (const sel of candidates) {
|
|
143
161
|
const hit = await firstVisible(page.locator(sel), 3);
|
|
144
162
|
if (!hit) continue;
|
|
145
163
|
try {
|
|
146
|
-
log('info', `[fb-pw] dismissing BS onboarding via "${sel}"`);
|
|
164
|
+
log('info', `[fb-pw] dismissing BS onboarding via "${sel}" (dlg="${dlgInfo.preview}")`);
|
|
147
165
|
await hit.click({ timeout: 2500 });
|
|
148
166
|
await page.waitForTimeout(700);
|
|
149
167
|
clicked = true;
|
|
@@ -152,9 +170,11 @@ async function dismissBsOnboarding(page, log) {
|
|
|
152
170
|
}
|
|
153
171
|
if (clicked) break;
|
|
154
172
|
}
|
|
173
|
+
// Clean up the marker attr regardless of outcome.
|
|
174
|
+
await page.evaluate(() => document.querySelectorAll("[__fbpw_onboarding__]").forEach((el) => el.removeAttribute('__fbpw_onboarding__'))).catch(() => {});
|
|
155
175
|
if (!clicked) {
|
|
156
|
-
|
|
157
|
-
|
|
176
|
+
// Don't blindly press Escape — would also close the Reels composer
|
|
177
|
+
// if it's the topmost dialog. Bail instead.
|
|
158
178
|
return;
|
|
159
179
|
}
|
|
160
180
|
}
|
|
@@ -1299,6 +1319,17 @@ async function run({ page, payload, log }) {
|
|
|
1299
1319
|
throw new Error(`FB publish: thumbnail_url provided but the "Chỉnh sửa hình thu nhỏ" overlay was never detected before publish (step ${step + 1}). Refusing to ship without custom thumb. Inspect dump screenshots in Temp\\cm-worker-pw\\.`);
|
|
1300
1320
|
}
|
|
1301
1321
|
log('info', `[fb-pw] click publish "${pub.verb}" via "${pub.sel}" (step ${step + 1})`);
|
|
1322
|
+
// DRY-RUN MODE (temporary, for QA): skip the actual publish click so
|
|
1323
|
+
// we can verify the upstream flow (modal scoping, video upload, thumb
|
|
1324
|
+
// step, metadata fill) without spawning real Reels every iteration.
|
|
1325
|
+
// Throws a recognisable error so the daemon marks the cmd failed
|
|
1326
|
+
// without retrying. REMOVE this block once the page-wall composer
|
|
1327
|
+
// fix is verified end-to-end.
|
|
1328
|
+
if (process.env.FB_PW_DRY_RUN === '1' || payload._dry_run === true) {
|
|
1329
|
+
await dumpInventory(page, log, `dry-run-at-publish-${step + 1}`);
|
|
1330
|
+
await dumpFailure(page, `dry-run-at-publish-${step + 1}`, log);
|
|
1331
|
+
throw new Error(`[fb-pw] DRY-RUN: reached publish step ${step + 1} successfully. Pub button found via "${pub.sel}" verb="${pub.verb}". Thumb=${customThumbDone ? 'uploaded' : 'NOT uploaded'}. NOT clicking. Inspect dump screenshots in Temp\\cm-worker-pw\\.`);
|
|
1332
|
+
}
|
|
1302
1333
|
// Snapshot the captured-IDs list RIGHT BEFORE the publish click. The
|
|
1303
1334
|
// network listener captures from EVERY graph response, including the
|
|
1304
1335
|
// pre-publish page wall feed (~100+ IDs). Only IDs captured AFTER
|