channel-worker 2.5.147 → 2.5.148

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.147",
3
+ "version": "2.5.148",
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": {
@@ -839,10 +839,13 @@ async function run({ page, payload, log }) {
839
839
  // Không có nó thì API không kết luận được kênh đã liên kết hay chưa, và cố
840
840
  // tình để ở "chưa rõ" còn hơn báo sai. Xem readDelegatePageId.
841
841
  if (pageRef) {
842
- const dg = await readDelegatePageId(page, pageRef.id).catch(() => ({ id: '', checked: false }));
842
+ const dg = await readDelegatePageId(page, pageRef.id).catch(() => ({ id: '', checked: false, reason: 'lỗi khi đọc' }));
843
843
  pageRef.delegate_id = dg.id;
844
844
  pageRef.delegate_checked = dg.checked;
845
- log('info', `[fb-stats] mã Trang (Shopee dùng): ${dg.id || (dg.checked ? 'không có — page kiểu cổ điển' : 'CHƯA rõ')}`);
845
+ // Giữ nguyên tiền tố "mã Trang (Shopee dùng): <số>" — grep log dựa vào nó.
846
+ // Lý do đi sau, để ca hụt nói được vì 0 mã hay vì nhiều mã.
847
+ const what = dg.id || (dg.checked ? 'không có — page kiểu cổ điển' : 'CHƯA rõ');
848
+ log('info', `[fb-stats] mã Trang (Shopee dùng): ${what}${dg.reason ? ` (${dg.reason})` : ''}`);
846
849
  }
847
850
  if (pageRef) log('info', `[fb-stats] page: ${pageRef.id ? `id ${pageRef.id}` : `handle ${pageRef.handle}`}`);
848
851
 
@@ -2153,34 +2153,76 @@ async function readPageIdFromDom(page) {
2153
2153
  // Khác `profile_id`/`actorID` (là của NGƯỜI ĐANG XEM), `delegate_page_id` nói
2154
2154
  // về TRANG ĐANG MỞ: đo trên 3 page lạ, nó trả đúng delegate của trang đó.
2155
2155
  //
2156
- // Trả { id, checked }:
2157
- // - đúng MỘT giá trị → id = nó, checked = true
2158
- // - KHÔNG có giá trị nào → page kiểu CỔ ĐIỂN (profile id chính là khoá
2159
- // Shopee) → id rỗng, checked = true. Chỉ dám kết luận vậy khi profile id
2160
- // KHÔNG mang hình dạng page kiểu mới; nếu nó là `61…` mà không đọc được
2161
- // delegate thì đó là đọc HỤT, không phải page cổ điển.
2162
- // - NHIỀU giá trị → profile quản nhiều page (đo thật ở
2163
- // `duong-nhan-cung-anh`: 2 delegate). Không đoán → checked = false, để bên
2164
- // API giữ trạng thái "chưa rõ" thay vì báo sai.
2165
- const NEW_STYLE_PROFILE_ID = /^61\d{12}$/;
2156
+ // ⚠️ MENU CHUYỂN TÀI KHOẢN cũng mang `delegate_page_id` (đo 02/10/2026, ca
2157
+ // "Bí Quyết Nhà Nông", profile NST khoe-khong-kho). Phiên đang đứng dưới danh
2158
+ // nghĩa page, nên trang nhúng sẵn mục để chuyển về TÀI KHOẢN CÁ NHÂN đã tạo
2159
+ // page (`ProfileSwitcherEligibleProfile`). Tài khoản cá nhân id dạng cũ `100…`
2160
+ // thì mục đó ghi `"delegate_page_id":null` — 5 profile đọc tốt đều vậy. Tài
2161
+ // khoản cá nhân "Lan Linh" (id dạng mới 61590196273118) lại mang một SỐ
2162
+ // (1193846817137262). Đếm chung mọi giá trị thì thành 2 mã → "chưa rõ" ở MỌI
2163
+ // lượt (47/47), và page không bao giờ được đối chiếu với Shopee. Tệ hơn: page
2164
+ // nào không lộ mã của chính nó thì bản cũ nhận nhầm mã của tài khoản cá nhân.
2165
+ //
2166
+ // Nên mỗi lần xuất hiện được phân loại theo VỊ TRÍ, không chỉ theo giá trị:
2167
+ // own — nằm cùng object phẳng với `"id":"<profile id của page>"`
2168
+ // (vd `"user":{"id":"6159…","name":"…","delegate_page_id":"…"}`
2169
+ // ở thanh điều hướng trái). Chắc nhất: gắn thẳng với page đang mở.
2170
+ // switcher — mục menu chuyển tài khoản. Không bao giờ là mã của page.
2171
+ // other — còn lại (vd bài viết trong lưới Reels).
2172
+ //
2173
+ // Hàm THUẦN và TỰ CHỨA (không dùng biến ngoài): `readDelegatePageId` gửi
2174
+ // nguyên văn mã nguồn của nó vào trang, nên test chạy đúng đoạn chạy trên
2175
+ // Facebook.
2176
+ function scanDelegatesInHtml(html, profileId) {
2177
+ const re = /"delegate_page_id"\s*:\s*"?(\d{5,25})"?/g;
2178
+ const pid = String(profileId || '');
2179
+ const own = new Set(); const switcher = new Set(); const other = new Set();
2180
+ let m; let n = 0;
2181
+ while ((m = re.exec(html)) && n < 60) {
2182
+ n++;
2183
+ const before = html.slice(Math.max(0, m.index - 600), m.index);
2184
+ const owner = before.match(/"id"\s*:\s*"(\d{5,25})"[^{}]*$/);
2185
+ if (pid && owner && owner[1] === pid) { own.add(m[1]); continue; }
2186
+ const after = html.slice(m.index + m[0].length, m.index + m[0].length + 400);
2187
+ const sw = after.indexOf('ProfileSwitcherEligibleProfile');
2188
+ const next = after.indexOf('"delegate_page_id"');
2189
+ if (sw !== -1 && (next === -1 || sw < next)) { switcher.add(m[1]); continue; }
2190
+ other.add(m[1]);
2191
+ }
2192
+ return { own: [...own], switcher: [...switcher], other: [...other] };
2193
+ }
2166
2194
 
2167
- async function readDelegatePageId(page, profileId = '') {
2168
- const found = await page.evaluate(() => {
2169
- const out = new Set();
2170
- const re = /"delegate_page_id"\s*:\s*"?(\d{5,25})"?/g;
2171
- const html = document.documentElement.innerHTML;
2172
- let m; let n = 0;
2173
- while ((m = re.exec(html)) && n < 20) { out.add(m[1]); n++; }
2174
- return [...out];
2175
- }).catch(() => null);
2195
+ // Trả { id, checked, reason }:
2196
+ // - đúng MỘT mã gắn với profile id của page → nhận.
2197
+ // - không có mã nào gắn được → luật cũ trên các mã còn lại, ĐÃ BỎ mục menu
2198
+ // chuyển tài khoản: đúng một mã thì nhận; NHIỀU mã thì không đoán
2199
+ // (`duong-nhan-cung-anh` 22/09: 2 mã), checked = false để API giữ "chưa rõ".
2200
+ // - KHÔNG có mã nào → page kiểu CỔ ĐIỂN (profile id chính là khoá Shopee) →
2201
+ // id rỗng, checked = true. Chỉ dám kết luận vậy khi profile id KHÔNG mang
2202
+ // hình dạng page kiểu mới; `61…` mà không có mã là đọc HỤT.
2203
+ // `reason` chỉ để ghi log: trước đây mọi ca hụt đều in "CHƯA rõ" nên không
2204
+ // ai biết hụt vì 0 mã hay vì nhiều mã.
2205
+ const NEW_STYLE_PROFILE_ID = /^61\d{12}$/;
2176
2206
 
2177
- if (found === null) return { id: '', checked: false };
2178
- if (found.length === 1) return { id: found[0], checked: true };
2179
- if (found.length === 0) {
2180
- // Không có delegate. Chỉ coi là page cổ điển khi profile id không phải dạng mới.
2181
- return { id: '', checked: !NEW_STYLE_PROFILE_ID.test(String(profileId || '')) };
2207
+ function pickDelegate(scan, profileId = '') {
2208
+ if (!scan) return { id: '', checked: false, reason: 'không đọc được trang' };
2209
+ const own = scan.own || [];
2210
+ const rest = scan.other || [];
2211
+ const sw = scan.switcher || [];
2212
+ if (own.length === 1) return { id: own[0], checked: true, reason: 'gắn với profile id của page' };
2213
+ if (own.length > 1) return { id: '', checked: false, reason: `${own.length} mã cùng gắn với profile id của page` };
2214
+ if (rest.length === 1) return { id: rest[0], checked: true, reason: 'mã duy nhất trên trang' };
2215
+ if (rest.length > 1) return { id: '', checked: false, reason: `${rest.length} mã khác nhau trên trang, không đoán` };
2216
+ if (NEW_STYLE_PROFILE_ID.test(String(profileId || ''))) {
2217
+ return { id: '', checked: false, reason: sw.length ? 'chỉ thấy mã của mục chuyển tài khoản' : 'trang không có mã nào' };
2182
2218
  }
2183
- return { id: '', checked: false }; // nhiều page trong cùng profile — không đoán
2219
+ return { id: '', checked: true, reason: 'page kiểu cổ điển' };
2220
+ }
2221
+
2222
+ async function readDelegatePageId(page, profileId = '') {
2223
+ const expr = `(${scanDelegatesInHtml.toString()})(document.documentElement.innerHTML, ${JSON.stringify(String(profileId || ''))})`;
2224
+ const scan = await page.evaluate(expr).catch(() => null);
2225
+ return pickDelegate(scan, profileId);
2184
2226
  }
2185
2227
 
2186
2228
  async function hasVisibleReelComposer(page) {
@@ -4772,6 +4814,8 @@ module.exports.__testables = {
4772
4814
  parsePageRef,
4773
4815
  readPageIdFromDom,
4774
4816
  readDelegatePageId,
4817
+ scanDelegatesInHtml,
4818
+ pickDelegate,
4775
4819
  discoverReelsTabUrls,
4776
4820
  openReelsTabWithTiles,
4777
4821
  networkIdVerdict,