channel-worker 2.5.33 → 2.5.34

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "2.5.33",
3
+ "version": "2.5.34",
4
4
  "description": "Channel Manager worker daemon — runs on remote machines to execute video pipeline jobs",
5
5
  "main": "lib/daemon.js",
6
6
  "bin": {
@@ -1743,6 +1743,62 @@ async function run({ page, payload, log }) {
1743
1743
  throw new Error(`FB rate-limited / spam-blocked this account — publish was NOT accepted. Detected phrase: "${blockHit}". Cool down account before retry.`);
1744
1744
  }
1745
1745
 
1746
+ // 7b) COMMIT VERIFY + RETRY. A Playwright click on an enabled "Đăng" can
1747
+ // register without FB actually publishing (handler no-op / transient
1748
+ // glitch) — the composer modal ("Cài đặt thước phim") just stays open
1749
+ // (this is the "đứng ở nút Đăng" the user reported). We used to still
1750
+ // return ok:true with an empty post_url → FALSE SUCCESS. Detect the
1751
+ // still-open composer, re-click "Đăng" a few times, and fail loudly if
1752
+ // it refuses to commit (so the cmd is marked failed, not done).
1753
+ const composerStillOpen = () => page.evaluate((verbs) => {
1754
+ const dlgs = document.querySelectorAll("[role='dialog']");
1755
+ for (const dlg of dlgs) {
1756
+ const r = dlg.getBoundingClientRect();
1757
+ if (r.width < 8 || r.height < 8) continue;
1758
+ const cs = getComputedStyle(dlg);
1759
+ if (cs.visibility === 'hidden' || cs.display === 'none') continue;
1760
+ const hay = ((dlg.getAttribute('aria-label') || '') + ' ' + (dlg.innerText || '')).toLowerCase();
1761
+ if (!/cài đặt thước phim|reel settings|tạo thước phim|create reel|create a reel|tạo bài viết|create post/.test(hay)) continue;
1762
+ const btns = dlg.querySelectorAll("button, [role='button']");
1763
+ for (const b of btns) {
1764
+ const t = ((b.innerText || '') + ' ' + (b.getAttribute('aria-label') || '')).trim();
1765
+ if (verbs.some((v) => t === v || t.split('\n').includes(v))) return true; // publish CTA still present → not committed
1766
+ }
1767
+ }
1768
+ return false;
1769
+ }, publishVerbs).catch(() => false);
1770
+
1771
+ for (let commitTry = 0; commitTry < 3 && (await composerStillOpen()); commitTry++) {
1772
+ log('warn', `[fb-pw] composer STILL open after publish click — re-clicking "Đăng" (retry ${commitTry + 1}/3)`);
1773
+ const reClicked = await page.evaluate((verbs) => {
1774
+ const dlgs = document.querySelectorAll("[role='dialog']");
1775
+ for (const dlg of dlgs) {
1776
+ const btns = dlg.querySelectorAll("button, [role='button']");
1777
+ for (const v of verbs) {
1778
+ for (const b of btns) {
1779
+ const t = (b.innerText || '').trim();
1780
+ const a = (b.getAttribute('aria-label') || '').trim();
1781
+ if ((t === v || a === v) && b.getAttribute('aria-disabled') !== 'true') {
1782
+ b.setAttribute('__fbpw_recommit__', '1');
1783
+ return true;
1784
+ }
1785
+ }
1786
+ }
1787
+ }
1788
+ return false;
1789
+ }, publishVerbs).catch(() => false);
1790
+ if (reClicked) {
1791
+ await page.locator("[__fbpw_recommit__='1']").click({ timeout: 5000 }).catch(() => {});
1792
+ await page.evaluate(() => document.querySelectorAll("[__fbpw_recommit__]").forEach((el) => el.removeAttribute('__fbpw_recommit__'))).catch(() => {});
1793
+ }
1794
+ await page.waitForTimeout(8000);
1795
+ }
1796
+ if (await composerStillOpen()) {
1797
+ await dumpInventory(page, log, 'composer-stuck-open');
1798
+ await dumpFailure(page, 'composer-stuck-open', log);
1799
+ throw new Error('FB publish KHÔNG commit — composer vẫn mở ở nút "Đăng" sau 3 lần thử (video CHƯA được đăng). Thử lại sau.');
1800
+ }
1801
+
1746
1802
  let postUrl = '';
1747
1803
 
1748
1804
  // (a) Title-anchored page-wall scrape — FB renders the just-published