diggylab 0.1.46 → 0.1.48

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.
Files changed (2) hide show
  1. package/cli.js +27 -6
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -180,8 +180,14 @@ function dedupeImageUrls(urls) {
180
180
  return order.map((pathname) => best.get(pathname).url).slice(0, 6);
181
181
  }
182
182
  function imageQuality(url) {
183
- const match = /[?&]stp=[^&]*?_p(\d+)x(\d+)/.exec(url);
184
- return match ? Math.max(Number(match[1]), Number(match[2])) : Number.MAX_SAFE_INTEGER;
183
+ if (/_fb30/i.test(url))
184
+ return 0;
185
+ const dimensions = [
186
+ ...url.matchAll(/(?:[?&](?:stp|cstp|ctp)=[^&]*?_s|_p)(\d+)x(\d+)/gi)
187
+ ];
188
+ if (!dimensions.length)
189
+ return Number.MAX_SAFE_INTEGER;
190
+ return Math.max(...dimensions.map((match) => Number(match[1]) * Number(match[2])));
185
191
  }
186
192
  function collectFallbackImageUrls(value, urls, depth) {
187
193
  if (!value || depth > 12 || urls.size >= 12)
@@ -423,10 +429,12 @@ function toComment(node) {
423
429
  const publishedAt = toIso(firstString(node, commentTimePaths));
424
430
  const id = firstString(node, [["id"]], false);
425
431
  const parentId = firstString(node, [["comment_direct_parent", "id"]], false);
432
+ const attachmentImages = getAttachmentImages(node);
426
433
  return {
427
434
  text: text.trim(),
428
435
  ...authorName ? { authorName } : {},
429
436
  ...authorAvatarUrl ? { authorAvatarUrl } : {},
437
+ ...attachmentImages.length ? { attachmentImages } : {},
430
438
  ...depth !== void 0 ? { depth } : {},
431
439
  ...id ? { id } : {},
432
440
  ...parentId ? { parentId } : {},
@@ -488,6 +496,12 @@ function mergeFacebookComments(items, limit) {
488
496
  existing.id = item.id;
489
497
  if (!existing.parentId && item.parentId)
490
498
  existing.parentId = item.parentId;
499
+ const attachmentImages = dedupeImageUrls([
500
+ ...existing.attachmentImages ?? [],
501
+ ...item.attachmentImages ?? []
502
+ ]);
503
+ if (attachmentImages.length)
504
+ existing.attachmentImages = attachmentImages;
491
505
  if (item.depth !== void 0) {
492
506
  existing.depth = existing.depth === void 0 ? item.depth : Math.min(existing.depth, item.depth);
493
507
  }
@@ -499,6 +513,7 @@ function mergeFacebookComments(items, limit) {
499
513
  text: text.slice(0, COMMENT_TEXT_LIMIT),
500
514
  ...authorName ? { authorName: authorName.slice(0, COMMENT_AUTHOR_LIMIT) } : {},
501
515
  ...item.authorAvatarUrl ? { authorAvatarUrl: item.authorAvatarUrl } : {},
516
+ ...item.attachmentImages?.length ? { attachmentImages: item.attachmentImages } : {},
502
517
  ...item.depth !== void 0 ? { depth: item.depth } : {},
503
518
  ...item.id ? { id: item.id } : {},
504
519
  ...item.parentId ? { parentId: item.parentId } : {},
@@ -608,10 +623,12 @@ async function extractFacebookDomComments(page) {
608
623
  };
609
624
  const texts = Array.from(article.querySelectorAll('[dir="auto"]')).filter((element) => belongsToArticle(element) && element.checkVisibility()).map((element) => readText(element)).filter(Boolean);
610
625
  const time = Array.from(article.querySelectorAll("time[datetime], abbr[data-utime]")).find((element) => belongsToArticle(element) && element.checkVisibility());
626
+ const attachmentImages = Array.from(article.querySelectorAll("img")).filter((image) => belongsToArticle(image) && image.checkVisibility()).map((image) => image.currentSrc || image.getAttribute("src") || "").filter((src) => /^https?:\/\//i.test(src) && /(scontent\.|fbcdn\.net)/i.test(src)).filter((src) => !/static\.xx\.fbcdn\.net|emoji\.php|rsrc\.php/i.test(src)).filter((src) => !/\/v\/t1\.30497-1\//i.test(src) && !/[?&]stp=cp0_/i.test(src));
611
627
  return {
612
628
  texts: Array.from(new Set(texts)),
613
629
  authorLabel: label,
614
- publishedAt: time?.getAttribute("datetime") ?? time?.getAttribute("data-utime") ?? void 0
630
+ publishedAt: time?.getAttribute("datetime") ?? time?.getAttribute("data-utime") ?? void 0,
631
+ ...attachmentImages.length ? { attachmentImages } : {}
615
632
  };
616
633
  }));
617
634
  return mergeFacebookComments(raw.flatMap((item) => {
@@ -622,9 +639,11 @@ async function extractFacebookDomComments(page) {
622
639
  if (!text)
623
640
  return [];
624
641
  const depth = parseCommentDepth(item.authorLabel);
642
+ const attachmentImages = dedupeImageUrls(item.attachmentImages ?? []);
625
643
  return [{
626
644
  text,
627
645
  ...authorName ? { authorName } : {},
646
+ ...attachmentImages.length ? { attachmentImages } : {},
628
647
  ...depth !== void 0 ? { depth } : {},
629
648
  ...toIso(item.publishedAt) ? { publishedAt: toIso(item.publishedAt) } : {}
630
649
  }];
@@ -638,14 +657,14 @@ function pickCommentText(texts, authorName) {
638
657
  }
639
658
  var COMMENT_UI_LABELS = /^(?:follow|theo dõi|like|thích|reply|trả lời|share|chia sẻ|see more|xem thêm|hide|ẩn|report|báo cáo)$/i;
640
659
  function commentKeyText(text) {
641
- const normalized = text.replace(/[\p{Extended_Pictographic}\u200d\uFE0F]/gu, "").replace(/[:;=8xX]-?[)(\]\[dDpP/\\|]+/g, "").replace(/\s+/g, " ").trim();
642
- return normalized || text.replace(/\s+/g, " ");
660
+ const normalized = text.replace(/[\p{Extended_Pictographic}\u200d\uFE0F]/gu, "").replace(/[:;=8xX]-?[)(\]\[dDpP/\\|]+/g, "").replace(/\s+/g, "");
661
+ return normalized || text.replace(/\s+/g, "");
643
662
  }
644
663
  function parseCommentAuthor(label) {
645
664
  const match = /^(?:bình luận|comment|trả lời|reply)\s+(?:dưới tên|by)\s+(.+)$/i.exec(label.trim());
646
665
  if (!match)
647
666
  return void 0;
648
- const name = match[1].replace(/\s+vào\s+.*$/i, "").replace(/\s+on\s+.*$/i, "").replace(/\s+to\s+.*$/i, "").replace(/\s+\d+\s*(?:giây|phút|giờ|ngày|tuần|tháng|năm|seconds?|minutes?|hours?|days?|weeks?|months?|years?)\s*(?:ago|trước)?\s*$/i, "").trim();
667
+ const name = match[1].replace(/\s+vào\s+.*$/i, "").replace(/\s+on\s+.*$/i, "").replace(/\s+to\s+.*$/i, "").replace(/\s+a\s+few\s+(?:seconds?|minutes?|hours?|days?)\s+ago\s*$/i, "").replace(/\s+(?:just\s+now|vừa\s+xong)\s*$/i, "").replace(/\s+(?:\d+|a|an|one|một|vài|few|several)\s+(?:giây|phút|giờ|ngày|tuần|tháng|năm|seconds?|minutes?|hours?|days?|weeks?|months?|years?)\s+(?:ago|trước)\s*$/i, "").trim();
649
668
  return name || void 0;
650
669
  }
651
670
  function parseCommentDepth(label) {
@@ -2088,11 +2107,13 @@ function normalizeCount(value) {
2088
2107
  function normalizeComments(payload) {
2089
2108
  const comments = payload.comments.slice(0, DESKTOP_POST_COMMENTS_MAX_LIMIT).map((comment) => {
2090
2109
  const authorAvatarUrl = normalizeMediaUrl(comment.authorAvatarUrl);
2110
+ const attachmentImages = (comment.attachmentImages ?? []).map(normalizeMediaUrl).filter((url) => Boolean(url)).slice(0, 6);
2091
2111
  const depth = normalizeCount(comment.depth);
2092
2112
  return {
2093
2113
  text: comment.text.trim().slice(0, 2e3),
2094
2114
  ...comment.authorName?.trim() ? { authorName: comment.authorName.trim().slice(0, 200) } : {},
2095
2115
  ...authorAvatarUrl ? { authorAvatarUrl } : {},
2116
+ ...attachmentImages.length ? { attachmentImages } : {},
2096
2117
  ...depth !== void 0 && depth <= 5 ? { depth } : {},
2097
2118
  ...comment.publishedAt ? { publishedAt: comment.publishedAt } : {}
2098
2119
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diggylab",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "DiggyLab Desktop Agent collects posts and information from Facebook Groups on a paired computer. (headless CLI)",
5
5
  "type": "module",
6
6
  "bin": {