channel-worker 2.5.20 → 2.5.22
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 +50 -27
package/package.json
CHANGED
|
@@ -283,7 +283,7 @@ async function run({ page, payload, log }) {
|
|
|
283
283
|
} = payload || {};
|
|
284
284
|
if (!video_url) throw new Error('No video_url provided');
|
|
285
285
|
|
|
286
|
-
log('info', '[fb-pw] selectors version=2026.06.
|
|
286
|
+
log('info', '[fb-pw] selectors version=2026.06.19c-posturl-network-first');
|
|
287
287
|
|
|
288
288
|
page.on('dialog', (d) => { d.accept().catch(() => {}); });
|
|
289
289
|
|
|
@@ -968,7 +968,9 @@ async function run({ page, payload, log }) {
|
|
|
968
968
|
const dlgs = [];
|
|
969
969
|
for (const d of allDlgs) {
|
|
970
970
|
const txt = (d.innerText || '').slice(0, 400);
|
|
971
|
-
|
|
971
|
+
// Match ALL reel-composer steps: "Tạo thước phim" (video step),
|
|
972
|
+
// the caption/cover step, and "Cài đặt thước phim" (settings step).
|
|
973
|
+
if (/thước phim|create reel|create a reel|reel settings/i.test(txt)) dlgs.push(d);
|
|
972
974
|
}
|
|
973
975
|
if (dlgs.length === 0) return null;
|
|
974
976
|
for (const dlg of dlgs) {
|
|
@@ -1165,6 +1167,27 @@ async function run({ page, payload, log }) {
|
|
|
1165
1167
|
// applied across ANY step, so nothing ships with FB's auto-thumb and a
|
|
1166
1168
|
// retry can't double-post.
|
|
1167
1169
|
if (!customThumbDone) {
|
|
1170
|
+
// DIAG: dump the reel-dialog buttons on this step so we can locate the
|
|
1171
|
+
// cover/thumbnail control when detection misses it (different UI variant).
|
|
1172
|
+
try {
|
|
1173
|
+
const diag = await page.evaluate(() => {
|
|
1174
|
+
const dlgs = [...document.querySelectorAll("[role='dialog']")]
|
|
1175
|
+
.filter(d => /thước phim|create reel|reel settings/i.test((d.innerText || '').slice(0, 400)));
|
|
1176
|
+
const out = [];
|
|
1177
|
+
for (const d of dlgs) {
|
|
1178
|
+
const hdr = (d.innerText || '').split('\n')[0].slice(0, 40);
|
|
1179
|
+
for (const el of d.querySelectorAll("[role='button'],button,[aria-label],img")) {
|
|
1180
|
+
const t = (el.innerText || '').trim().slice(0, 28);
|
|
1181
|
+
const al = (el.getAttribute('aria-label') || '').trim().slice(0, 40);
|
|
1182
|
+
const r = el.getBoundingClientRect();
|
|
1183
|
+
if (r.width < 10 || r.height < 10) continue;
|
|
1184
|
+
if (t || al) out.push(`[${hdr}] <${el.tagName.toLowerCase()}> t="${t}" al="${al}" ${Math.round(r.width)}x${Math.round(r.height)}`);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return out.slice(0, 45);
|
|
1188
|
+
}).catch(() => []);
|
|
1189
|
+
log('info', `[fb-pw] thumb-diag step ${step + 1}: ${JSON.stringify(diag)}`);
|
|
1190
|
+
} catch { /* diag best-effort */ }
|
|
1168
1191
|
log('info', '[fb-pw] thumb-edit pill not on this step yet — advancing via "Tiếp" to retry on the next step');
|
|
1169
1192
|
}
|
|
1170
1193
|
}
|
|
@@ -1891,12 +1914,30 @@ async function run({ page, payload, log }) {
|
|
|
1891
1914
|
}
|
|
1892
1915
|
}
|
|
1893
1916
|
|
|
1894
|
-
// (a.2)
|
|
1895
|
-
//
|
|
1896
|
-
//
|
|
1897
|
-
//
|
|
1898
|
-
//
|
|
1899
|
-
//
|
|
1917
|
+
// (a.2) Graph API network capture — AUTHORITATIVE. The publish-mutation
|
|
1918
|
+
// response carries the JUST-published reel ID. Only consider IDs
|
|
1919
|
+
// captured AFTER the publish-click snapshot (pre-snapshot IDs are the
|
|
1920
|
+
// page-wall feed pre-render, NOT the publish mutation). Take the FIRST
|
|
1921
|
+
// new ID (the mutation response comes back before feed-reload
|
|
1922
|
+
// responses). Prefer this over scraping the reels tab: the new reel
|
|
1923
|
+
// often isn't on the tab yet (still processing), so the tab's "first
|
|
1924
|
+
// tile" is a STALE older reel — which is the bug this ordering fixes.
|
|
1925
|
+
if (!postUrl && capturedReelIds.length > capturedReelIdsSnapshotLen) {
|
|
1926
|
+
const newIds = capturedReelIds.slice(capturedReelIdsSnapshotLen);
|
|
1927
|
+
const preSet = new Set(capturedReelIds.slice(0, capturedReelIdsSnapshotLen));
|
|
1928
|
+
const trulyNew = newIds.filter((id) => !preSet.has(id));
|
|
1929
|
+
if (trulyNew.length) {
|
|
1930
|
+
const firstNew = trulyNew[0];
|
|
1931
|
+
postUrl = `https://www.facebook.com/reel/${firstNew}/`;
|
|
1932
|
+
log('info', `[fb-pw] post URL from network (FIRST new ID after snapshot): ${postUrl} (snapshotLen=${capturedReelIdsSnapshotLen} total=${capturedReelIds.length} new=${trulyNew.length})`);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
// (a.3) LAST-RESORT: first reel tile on the profile reels tab. UNRELIABLE —
|
|
1937
|
+
// the just-published reel may not be on the tab yet (still
|
|
1938
|
+
// processing), so the first tile can be a STALE older reel. Only used
|
|
1939
|
+
// when every authoritative source above (fresh-timestamp tile,
|
|
1940
|
+
// title-match, inline CTA, network capture) returned nothing.
|
|
1900
1941
|
if (!postUrl) {
|
|
1901
1942
|
const tileHref = await page.evaluate(() => {
|
|
1902
1943
|
const anchors = document.querySelectorAll("a[role='link']");
|
|
@@ -1911,25 +1952,7 @@ async function run({ page, payload, log }) {
|
|
|
1911
1952
|
}).catch(() => null);
|
|
1912
1953
|
if (tileHref) {
|
|
1913
1954
|
postUrl = tileHref.href.startsWith('http') ? tileHref.href : `https://www.facebook.com${tileHref.href}`;
|
|
1914
|
-
log('
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
// (b) Graph API network capture — only consider IDs captured AFTER the
|
|
1919
|
-
// publish click snapshot (pre-snapshot IDs are from the page-wall
|
|
1920
|
-
// feed pre-render, NOT the publish mutation). Take the FIRST new ID
|
|
1921
|
-
// since FB's publish-mutation response comes back before any
|
|
1922
|
-
// feed-reload responses.
|
|
1923
|
-
if (!postUrl && capturedReelIds.length > capturedReelIdsSnapshotLen) {
|
|
1924
|
-
const newIds = capturedReelIds.slice(capturedReelIdsSnapshotLen);
|
|
1925
|
-
// Filter out IDs that appeared in the pre-snapshot to be safe (Set
|
|
1926
|
-
// diff). Then take the FIRST new one.
|
|
1927
|
-
const preSet = new Set(capturedReelIds.slice(0, capturedReelIdsSnapshotLen));
|
|
1928
|
-
const trulyNew = newIds.filter((id) => !preSet.has(id));
|
|
1929
|
-
if (trulyNew.length) {
|
|
1930
|
-
const firstNew = trulyNew[0];
|
|
1931
|
-
postUrl = `https://www.facebook.com/reel/${firstNew}/`;
|
|
1932
|
-
log('info', `[fb-pw] post URL from network (FIRST new ID after snapshot): ${postUrl} (snapshotLen=${capturedReelIdsSnapshotLen} total=${capturedReelIds.length} new=${trulyNew.length})`);
|
|
1955
|
+
log('warn', `[fb-pw] post URL from FIRST reel tile on reels_tab (LAST-RESORT, may be STALE): ${postUrl}`);
|
|
1933
1956
|
}
|
|
1934
1957
|
}
|
|
1935
1958
|
|