channel-worker 2.5.38 → 2.5.40
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/lib/command-poller.js +8 -1
- package/package.json +1 -1
- package/scripts/upload_facebook.js +18 -2
package/lib/command-poller.js
CHANGED
|
@@ -1456,12 +1456,16 @@ class CommandPoller {
|
|
|
1456
1456
|
let parallelLimit = 2; // sane default if /workers/me fails or is
|
|
1457
1457
|
// unavailable on an older API; effective limit
|
|
1458
1458
|
// is still bounded by server-side enforcement.
|
|
1459
|
+
let independentAccounts = false; // when true: renderers are SEPARATE Flow
|
|
1460
|
+
// accounts → run all concurrently, skip the
|
|
1461
|
+
// shared-account round-robin close-idle rotation.
|
|
1459
1462
|
try {
|
|
1460
1463
|
if (this.api.getMyWorker) {
|
|
1461
1464
|
const me = await this.api.getMyWorker();
|
|
1462
1465
|
if (me && typeof me.parallel_limit === 'number') {
|
|
1463
1466
|
parallelLimit = Math.max(0, me.parallel_limit);
|
|
1464
1467
|
}
|
|
1468
|
+
if (me && me.independent_accounts) independentAccounts = true;
|
|
1465
1469
|
}
|
|
1466
1470
|
} catch (e) {
|
|
1467
1471
|
if (this.config.verbose) console.warn('[scene-dispatch] getMyWorker failed, using default:', e.message);
|
|
@@ -1483,7 +1487,10 @@ class CommandPoller {
|
|
|
1483
1487
|
// browser idle on Flow page keeps refreshing tokens / pinging
|
|
1484
1488
|
// telemetry → Veo flags "2 concurrent sessions per account" → captcha.
|
|
1485
1489
|
// Closing it = 0 idle sessions, only 1 active at a time.
|
|
1486
|
-
|
|
1490
|
+
// Round-robin close-idle is a SHARED-ACCOUNT safety (keep ≤1 Flow session
|
|
1491
|
+
// live per Google account). With independent_accounts every renderer is
|
|
1492
|
+
// its own account → skip it entirely and let them all run concurrently.
|
|
1493
|
+
if (!independentAccounts && queueCount > 0 && stillOffline.length > 0 && runningRenderers.length > 0) {
|
|
1487
1494
|
const stoppedNames = [];
|
|
1488
1495
|
for (const r of [...runningRenderers]) {
|
|
1489
1496
|
// Skip externally-launched profiles (user opened manually via NST UI)
|
package/package.json
CHANGED
|
@@ -1556,14 +1556,30 @@ async function run({ page, payload, log }) {
|
|
|
1556
1556
|
// Re-find + re-click up to 3×, and on the last try fall back to a raw
|
|
1557
1557
|
// JS dispatch (bypasses Playwright's obscured/stable guards).
|
|
1558
1558
|
let clickedPublish = false;
|
|
1559
|
+
let attemptedClick = false;
|
|
1560
|
+
// The publish button is gone → the composer closed, which on FB means
|
|
1561
|
+
// the post was ACCEPTED. Critical guard against the false-failure that
|
|
1562
|
+
// caused double-posts: FB registers the click and closes the composer,
|
|
1563
|
+
// but Playwright's click() promise still throws a timeout as the node
|
|
1564
|
+
// detaches. Treating that as a failure marked the idea unpublished →
|
|
1565
|
+
// the user re-posted → duplicate reel. So: if the button vanished
|
|
1566
|
+
// after we clicked, it went through.
|
|
1567
|
+
const publishBtnGone = async () => !(await findByVerbs(publishVerbs, { requireBottomHalf: true }));
|
|
1559
1568
|
for (let attempt = 0; attempt < 3 && !clickedPublish; attempt++) {
|
|
1560
1569
|
const target = attempt === 0 ? pub : await findByVerbs(publishVerbs, { requireBottomHalf: true });
|
|
1561
|
-
if (!target) {
|
|
1570
|
+
if (!target) {
|
|
1571
|
+
if (attemptedClick) { clickedPublish = true; log('info', '[fb-pw] publish button gone after click → post accepted'); break; }
|
|
1572
|
+
await page.waitForTimeout(1500); continue;
|
|
1573
|
+
}
|
|
1574
|
+
attemptedClick = true;
|
|
1562
1575
|
try {
|
|
1563
1576
|
await target.hit.click({ timeout: 15000 });
|
|
1564
1577
|
clickedPublish = true;
|
|
1565
1578
|
} catch (ce) {
|
|
1566
|
-
log('warn', `[fb-pw] publish click attempt ${attempt + 1}/3
|
|
1579
|
+
log('warn', `[fb-pw] publish click attempt ${attempt + 1}/3 threw: ${ce.message.slice(0, 90)}`);
|
|
1580
|
+
// Click may have registered before the node detached — if the
|
|
1581
|
+
// button is now gone, the post went through.
|
|
1582
|
+
if (await publishBtnGone()) { clickedPublish = true; log('info', '[fb-pw] click threw but publish button gone → post accepted'); break; }
|
|
1567
1583
|
if (attempt === 2) {
|
|
1568
1584
|
const js = await page.evaluate(() => {
|
|
1569
1585
|
const el = document.querySelector("[__fbpw_target__='1']")
|