channel-worker 2.5.96 → 2.5.97
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 +73 -27
package/package.json
CHANGED
|
@@ -694,33 +694,24 @@ async function confirmPublishDialog({ firstHit, tagConfirmButton, clickTagged, c
|
|
|
694
694
|
|
|
695
695
|
// Link tab Reels của Page — dùng ở CẢ HAI đầu lượt đăng (chụp ảnh nền trước
|
|
696
696
|
// khi đăng, quét lại sau khi đăng). Ba chiến lược, giữ nguyên từ bản cũ.
|
|
697
|
-
async function discoverReelsTabUrl(page) {
|
|
698
|
-
|
|
699
|
-
const
|
|
700
|
-
for (const a of
|
|
701
|
-
const
|
|
702
|
-
if (
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
for (const a of profAnchors) {
|
|
706
|
-
const h = a.getAttribute('href') || '';
|
|
707
|
-
const m = h.match(/\/profile\.php\?id=(\d+)/);
|
|
708
|
-
if (m) return `https://www.facebook.com/profile.php?id=${m[1]}&sk=reels_tab`;
|
|
709
|
-
}
|
|
710
|
-
const tlAnchors = document.querySelectorAll("a[aria-label*='Dòng thời gian'], a[aria-label*='Timeline']");
|
|
711
|
-
for (const a of tlAnchors) {
|
|
712
|
-
const h = a.getAttribute('href') || '';
|
|
713
|
-
const m = h.match(/^\/([A-Za-z0-9._-]{3,})\/?(?:\?|$)/);
|
|
714
|
-
if (m && !['profile.php', 'reel', 'video', 'videos'].includes(m[1])) {
|
|
715
|
-
return `https://www.facebook.com/${m[1]}/?sk=reels_tab`;
|
|
716
|
-
}
|
|
717
|
-
if (h.match(/\/profile\.php\?id=(\d+)/)) {
|
|
718
|
-
const pid = h.match(/\/profile\.php\?id=(\d+)/)[1];
|
|
719
|
-
return `https://www.facebook.com/profile.php?id=${pid}&sk=reels_tab`;
|
|
720
|
-
}
|
|
697
|
+
async function discoverReelsTabUrl(page, log = null) {
|
|
698
|
+
const anchors = await page.evaluate(() => {
|
|
699
|
+
const out = [];
|
|
700
|
+
for (const a of document.querySelectorAll('a[href]')) {
|
|
701
|
+
const href = a.getAttribute('href') || '';
|
|
702
|
+
if (!href || href.startsWith('#') || href.startsWith('javascript:')) continue;
|
|
703
|
+
out.push({ href: href.slice(0, 200), aria: (a.getAttribute('aria-label') || '').slice(0, 80) });
|
|
704
|
+
if (out.length >= 400) break;
|
|
721
705
|
}
|
|
722
|
-
return
|
|
723
|
-
}).catch(() =>
|
|
706
|
+
return out;
|
|
707
|
+
}).catch(() => []);
|
|
708
|
+
const url = pickReelsTabUrl(anchors);
|
|
709
|
+
if (!url && log) {
|
|
710
|
+
// Chẩn đoán: in vài href "giống của Page" để lần sau thêm đúng chiến lược.
|
|
711
|
+
const sample = anchors.map((a) => a.href).filter((h) => /^\/(?:profile\.php|\d{8,}|[A-Za-z0-9._-]{3,}\/?(?:\?|$))/.test(h)).slice(0, 8);
|
|
712
|
+
log('info', `[fb-pw] tìm tab Reels: ${anchors.length} anchor, không khớp chiến lược nào; mẫu: ${JSON.stringify(sample)}`);
|
|
713
|
+
}
|
|
714
|
+
return url;
|
|
724
715
|
}
|
|
725
716
|
|
|
726
717
|
// Mọi reel ID đang hiện trên tab Reels, theo thứ tự DOM (mới nhất trước).
|
|
@@ -750,6 +741,44 @@ function diffNewReelIds(beforeIds, afterIds) {
|
|
|
750
741
|
return (afterIds || []).filter((id) => !before.has(id));
|
|
751
742
|
}
|
|
752
743
|
|
|
744
|
+
// Chữ ký của chính composer (mọi bước của wizard). Dùng để KHÔNG bao giờ bấm
|
|
745
|
+
// nhầm vào nút của composer khi đang định bấm nút của hộp ảnh bìa.
|
|
746
|
+
const COMPOSER_SIGNATURE_RE = /Cài đặt thước phim|Tạo thước phim|Chỉnh sửa thước phim|Reel settings|Create (?:a )?reel|Edit reel/i;
|
|
747
|
+
function isComposerDialogSignature(text) {
|
|
748
|
+
return COMPOSER_SIGNATURE_RE.test(String(text || ''));
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Chọn link tab Reels từ danh sách anchor của trang (thuần, test được).
|
|
752
|
+
// Chiến lược 1-3 giữ nguyên từ bản cũ; 4-5 thêm 09/09 vì trên TRANG CHỦ (lúc
|
|
753
|
+
// chụp ảnh nền trước khi đăng) không có anchor profile.php/Dòng thời gian —
|
|
754
|
+
// 2/2 lượt "không tìm được link tab Reels trước khi đăng". Trang chủ của Page
|
|
755
|
+
// có shortcut bên trái trỏ /<id số>/ hoặc /<handle>/, và đôi khi /<id>/reels/.
|
|
756
|
+
function pickReelsTabUrl(anchors) {
|
|
757
|
+
const list = (anchors || []).map((a) => ({ href: String(a.href || ''), aria: String(a.aria || '') }));
|
|
758
|
+
const abs = (h) => (h.startsWith('http') ? h : `https://www.facebook.com${h}`);
|
|
759
|
+
for (const a of list) if (/sk=reels_tab/.test(a.href)) return abs(a.href);
|
|
760
|
+
for (const a of list) {
|
|
761
|
+
const m = a.href.match(/\/profile\.php\?id=(\d+)/);
|
|
762
|
+
if (m) return `https://www.facebook.com/profile.php?id=${m[1]}&sk=reels_tab`;
|
|
763
|
+
}
|
|
764
|
+
for (const a of list) {
|
|
765
|
+
if (!/Dòng thời gian|Timeline/i.test(a.aria)) continue;
|
|
766
|
+
const m = a.href.match(/^(?:https?:\/\/(?:www\.)?facebook\.com)?\/([A-Za-z0-9._-]{3,})\/?(?:\?|$)/);
|
|
767
|
+
if (m && !['profile.php', 'reel', 'video', 'videos', 'reels'].includes(m[1])) return `https://www.facebook.com/${m[1]}/?sk=reels_tab`;
|
|
768
|
+
}
|
|
769
|
+
// 4. /<id số>/reels/ hoặc /<id số>/ — shortcut của Page trên trang chủ.
|
|
770
|
+
for (const a of list) {
|
|
771
|
+
const m = a.href.match(/^(?:https?:\/\/(?:www\.)?facebook\.com)?\/(\d{10,20})(?:\/reels)?\/?(?:\?|$)/);
|
|
772
|
+
if (m) return `https://www.facebook.com/profile.php?id=${m[1]}&sk=reels_tab`;
|
|
773
|
+
}
|
|
774
|
+
// 5. /<handle>/reels/ — Page có tên riêng.
|
|
775
|
+
for (const a of list) {
|
|
776
|
+
const m = a.href.match(/^(?:https?:\/\/(?:www\.)?facebook\.com)?\/([A-Za-z0-9._-]{3,})\/reels\/?(?:\?|$)/);
|
|
777
|
+
if (m && !['profile.php', 'reel', 'video', 'videos'].includes(m[1])) return `https://www.facebook.com/${m[1]}/?sk=reels_tab`;
|
|
778
|
+
}
|
|
779
|
+
return null;
|
|
780
|
+
}
|
|
781
|
+
|
|
753
782
|
async function hasVisibleReelComposer(page) {
|
|
754
783
|
return page.evaluate(() => {
|
|
755
784
|
for (const dlg of document.querySelectorAll("[role='dialog']")) {
|
|
@@ -891,7 +920,7 @@ async function runOnce({ page, payload, log }) {
|
|
|
891
920
|
// về, ~6-8s. Hỏng thì bỏ qua, không chặn lượt đăng.
|
|
892
921
|
let reelIdsBefore = null;
|
|
893
922
|
try {
|
|
894
|
-
const tabUrl = await discoverReelsTabUrl(page);
|
|
923
|
+
const tabUrl = await discoverReelsTabUrl(page, log);
|
|
895
924
|
if (tabUrl) {
|
|
896
925
|
await page.goto(tabUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 });
|
|
897
926
|
await pause(page, 3500);
|
|
@@ -1884,12 +1913,27 @@ async function runOnce({ page, payload, log }) {
|
|
|
1884
1913
|
const head = dlg ? (dlg.innerText || '').slice(0, 40).replace(/\s+/g, ' ') : '';
|
|
1885
1914
|
return `${aria} | ${head}`;
|
|
1886
1915
|
}).catch(() => '?');
|
|
1916
|
+
// ĐÃ CÓ BẰNG CHỨNG (2.5.96, 09/09 23:30, 2/2 lượt): nút "Lưu" bấm
|
|
1917
|
+
// lại nằm trong "Cài đặt thước phim" = nút LƯU NHÁP của
|
|
1918
|
+
// composer, không phải của hộp ảnh bìa (hộp đã đóng, nhưng
|
|
1919
|
+
// isThumbnailEditorVisible vẫn thấy chữ "Chỉnh sửa hình thu
|
|
1920
|
+
// nhỏ" trên pill của composer nên tưởng còn mở). Bấm vào là
|
|
1921
|
+
// FB lưu nháp, đóng composer, về trang chủ → "composer đóng
|
|
1922
|
+
// giữa chừng" (3/5 lượt tối 09/09, kể cả file nén 42 MB).
|
|
1923
|
+
// Nút thuộc composer thì KHÔNG bấm; và vì hộp ảnh bìa không
|
|
1924
|
+
// còn nút Lưu nào nghĩa là nó đã đóng → coi như xong.
|
|
1925
|
+
if (isComposerDialogSignature(where)) {
|
|
1926
|
+
log('warn', `[fb-pw] re-click Lưu BỎ QUA: nút thuộc composer (${where.slice(0, 60)}) — hộp ảnh bìa đã đóng, không bấm lưu nháp`);
|
|
1927
|
+
modalClosed = true;
|
|
1928
|
+
break;
|
|
1929
|
+
}
|
|
1887
1930
|
log('info', `[fb-pw] re-click Lưu → nút nằm trong: ${where}`);
|
|
1888
1931
|
try {
|
|
1889
1932
|
await btn.click({ timeout: 2500 });
|
|
1890
1933
|
break;
|
|
1891
1934
|
} catch {}
|
|
1892
1935
|
}
|
|
1936
|
+
if (modalClosed) break;
|
|
1893
1937
|
}
|
|
1894
1938
|
await pause(page, 1000);
|
|
1895
1939
|
}
|
|
@@ -3107,6 +3151,8 @@ module.exports.__testables = {
|
|
|
3107
3151
|
resilientClick,
|
|
3108
3152
|
confirmPublishDialog,
|
|
3109
3153
|
diffNewReelIds,
|
|
3154
|
+
pickReelsTabUrl,
|
|
3155
|
+
isComposerDialogSignature,
|
|
3110
3156
|
discoverReelsTabUrl,
|
|
3111
3157
|
scrapeReelTileIds,
|
|
3112
3158
|
muteClickInterceptors,
|