channel-worker 2.5.58 → 2.5.59
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 +34 -0
package/package.json
CHANGED
|
@@ -414,6 +414,31 @@ function safeComposerRetryError(message) {
|
|
|
414
414
|
return err;
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
// Toast "Thông báo mới" (ai đó thích/bình luận reel) nổi lên góc trái và ĂN
|
|
418
|
+
// CÚ CLICK: 23/08 hai lần liên tiếp bot bấm "Tiếp" thì FB nhảy sang xem reel
|
|
419
|
+
// cũ, composer đóng → "final description field not found". Đóng toast trước
|
|
420
|
+
// mỗi bước bấm; không có toast thì trả 0, rất rẻ.
|
|
421
|
+
async function dismissToasts(page) {
|
|
422
|
+
return page.evaluate(() => {
|
|
423
|
+
let closed = 0;
|
|
424
|
+
const isToast = (el) => {
|
|
425
|
+
const t = (el.innerText || '').slice(0, 120);
|
|
426
|
+
return /Thông báo mới|New notification|vừa bình luận|thích thước phim|liked your/i.test(t);
|
|
427
|
+
};
|
|
428
|
+
const roots = [...document.querySelectorAll("[role='dialog'], [role='alert'], [role='status'], div[data-visualcompletion='ignore-dynamic']")];
|
|
429
|
+
for (const r of roots) {
|
|
430
|
+
const rect = r.getBoundingClientRect();
|
|
431
|
+
if (rect.width < 40 || rect.height < 30) continue;
|
|
432
|
+
if (!isToast(r)) continue;
|
|
433
|
+
// Nút đóng: aria-label Đóng/Close, hoặc <div role=button> chứa dấu X.
|
|
434
|
+
const btn = r.querySelector("[aria-label='Đóng'], [aria-label='Close'], [aria-label*='óng thông báo']")
|
|
435
|
+
|| [...r.querySelectorAll("[role='button'], button")].find((b) => (b.getAttribute('aria-label') || '').length < 12);
|
|
436
|
+
if (btn) { btn.click(); closed++; }
|
|
437
|
+
}
|
|
438
|
+
return closed;
|
|
439
|
+
}).catch(() => 0);
|
|
440
|
+
}
|
|
441
|
+
|
|
417
442
|
async function hasVisibleReelComposer(page) {
|
|
418
443
|
return page.evaluate(() => {
|
|
419
444
|
for (const dlg of document.querySelectorAll("[role='dialog']")) {
|
|
@@ -2043,6 +2068,9 @@ async function runOnce({ page, payload, log }) {
|
|
|
2043
2068
|
}
|
|
2044
2069
|
|
|
2045
2070
|
// No publish yet — advance via Tiếp.
|
|
2071
|
+
// Đóng toast thông báo TRƯỚC: nó nổi đúng vùng thao tác và cướp cú click.
|
|
2072
|
+
const _toasts = await dismissToasts(page);
|
|
2073
|
+
if (_toasts) log('info', `[fb-pw] đóng ${_toasts} toast thông báo trước khi bấm Tiếp`);
|
|
2046
2074
|
const next = await findByVerbs(nextVerbs);
|
|
2047
2075
|
if (!next) {
|
|
2048
2076
|
// Final "Cài đặt thước phim" step: the only action is "Đăng", which FB
|
|
@@ -2062,6 +2090,12 @@ async function runOnce({ page, payload, log }) {
|
|
|
2062
2090
|
if (waitResult.enabled) { step--; continue; }
|
|
2063
2091
|
await dumpInventory(page, log, `no-advance-${step + 1}`);
|
|
2064
2092
|
await dumpFailure(page, `no-advance-${step + 1}`, log);
|
|
2093
|
+
// Composer biến mất (URL nhảy sang /reel/… vì toast cướp click, hoặc
|
|
2094
|
+
// FB tự đóng) → CHẠY LẠI cả lượt upload thay vì báo lỗi khó hiểu.
|
|
2095
|
+
// An toàn vì chưa hề bấm Đăng ở nhánh này.
|
|
2096
|
+
if (!(await hasVisibleReelComposer(page))) {
|
|
2097
|
+
throw safeComposerRetryError(`FB composer đóng giữa chừng (đang ở ${page.url().slice(0, 80)}) — chạy lại lượt đăng`);
|
|
2098
|
+
}
|
|
2065
2099
|
if (!fillState.description) {
|
|
2066
2100
|
throw new Error(`FB final description field not found at step ${step + 1}`);
|
|
2067
2101
|
}
|