channel-worker 2.5.35 → 2.5.36
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_photo.js +38 -24
package/package.json
CHANGED
|
@@ -221,45 +221,59 @@ async function run({ page, payload, log }) {
|
|
|
221
221
|
|
|
222
222
|
// 6) Click "Đăng".
|
|
223
223
|
log('info', '[fbphoto] clicking publish…');
|
|
224
|
-
|
|
224
|
+
// Tag the first enabled button inside the composer matching `verbs`
|
|
225
|
+
// (bottom-half CTA preferred). Returns the matched verb, or null.
|
|
226
|
+
const tagCta = async (verbs) => page.evaluate((vbs) => {
|
|
225
227
|
const dlg = document.querySelector("[role='dialog']") || document;
|
|
228
|
+
const btns = [...dlg.querySelectorAll("div[role='button'], button, [role='button']")];
|
|
226
229
|
for (const v of vbs) {
|
|
227
|
-
for (const b of
|
|
230
|
+
for (const b of btns) {
|
|
228
231
|
const t = (b.innerText || '').trim();
|
|
229
232
|
const a = (b.getAttribute('aria-label') || '').trim();
|
|
230
233
|
if ((t === v || a === v) && b.getAttribute('aria-disabled') !== 'true') {
|
|
231
|
-
b.
|
|
232
|
-
|
|
234
|
+
const r = b.getBoundingClientRect();
|
|
235
|
+
if (r.width < 8 || r.height < 8) continue;
|
|
236
|
+
b.setAttribute('__fbphoto_cta__', '1');
|
|
237
|
+
return v;
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
|
-
return
|
|
237
|
-
},
|
|
241
|
+
return null;
|
|
242
|
+
}, verbs).catch(() => null);
|
|
243
|
+
const clickTaggedCta = async () => {
|
|
244
|
+
await page.locator("[__fbphoto_cta__='1']").click({ timeout: 5000 }).catch(() => {});
|
|
245
|
+
await page.evaluate(() => document.querySelectorAll('[__fbphoto_cta__]').forEach((e) => e.removeAttribute('__fbphoto_cta__'))).catch(() => {});
|
|
246
|
+
};
|
|
238
247
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
248
|
+
// Step loop: the FB photo composer is MULTI-STEP — "Tiếp" advances through
|
|
249
|
+
// audience/settings screens; only the LAST step shows "Đăng"/"Chia sẻ ngay"
|
|
250
|
+
// (the failing run stopped here: it saw a "Tiếp", not a publish button).
|
|
251
|
+
// Prefer a publish button when present; else advance via "Tiếp". Retry a
|
|
252
|
+
// few times when neither is enabled yet (FB disables while ingesting).
|
|
253
|
+
const nextVerbs = ['Tiếp', 'Tiếp theo', 'Next', 'Continue'];
|
|
254
|
+
let published = false;
|
|
255
|
+
let stalls = 0;
|
|
256
|
+
for (let step = 0; step < 8 && !published; step++) {
|
|
257
|
+
const pubHit = await tagCta(publishVerbs);
|
|
258
|
+
if (pubHit) { log('info', `[fbphoto] publish via "${pubHit}" (step ${step + 1})`); await clickTaggedCta(); published = true; break; }
|
|
259
|
+
const nextHit = await tagCta(nextVerbs);
|
|
260
|
+
if (nextHit) { log('info', `[fbphoto] advance via "${nextHit}" (step ${step + 1})`); await clickTaggedCta(); await page.waitForTimeout(2800); stalls = 0; continue; }
|
|
261
|
+
// Neither publish nor Tiếp enabled — FB still ingesting the photo. Wait.
|
|
262
|
+
if (++stalls > 10) break; // ~30s of no CTA → give up
|
|
263
|
+
log('info', `[fbphoto] no CTA yet at step ${step + 1} — waiting…`);
|
|
264
|
+
step--; // don't count a pure wait against the step budget
|
|
265
|
+
await page.waitForTimeout(3000);
|
|
249
266
|
}
|
|
250
|
-
if (!
|
|
267
|
+
if (!published) {
|
|
251
268
|
await dumpFailure(page, 'no-publish-btn', log);
|
|
252
|
-
throw new Error('FB: nút "Đăng"
|
|
269
|
+
throw new Error('FB: không tìm thấy nút "Đăng" sau các bước "Tiếp" (composer đổi layout?).');
|
|
253
270
|
}
|
|
254
271
|
|
|
255
|
-
//
|
|
272
|
+
// Verify commit + retry — a click can register without FB posting.
|
|
256
273
|
await page.waitForTimeout(6000);
|
|
257
274
|
for (let commitTry = 0; commitTry < 3 && (await composerStillOpen(page, publishVerbs)); commitTry++) {
|
|
258
|
-
log('warn', `[fbphoto] composer still open — re-clicking
|
|
259
|
-
if (await
|
|
260
|
-
await page.locator("[__fbphoto_pub__='1']").click({ timeout: 5000 }).catch(() => {});
|
|
261
|
-
await page.evaluate(() => document.querySelectorAll('[__fbphoto_pub__]').forEach((e) => e.removeAttribute('__fbphoto_pub__'))).catch(() => {});
|
|
262
|
-
}
|
|
275
|
+
log('warn', `[fbphoto] composer still open — re-clicking publish (retry ${commitTry + 1}/3)`);
|
|
276
|
+
if (await tagCta(publishVerbs)) await clickTaggedCta();
|
|
263
277
|
await page.waitForTimeout(6000);
|
|
264
278
|
}
|
|
265
279
|
if (await composerStillOpen(page, publishVerbs)) {
|