@danhachuel/thunderbolt 0.6.15 → 0.6.16

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.
@@ -152,7 +152,16 @@ def render_meta_api_cards(settings: dict[str, Any], kind: str) -> None:
152
152
 
153
153
  def _instagram_profiles() -> list[dict[str, Any]]:
154
154
  records = read_json("channels.json", [])
155
- return [item for item in records if isinstance(item, dict) and _clean(item.get("platform")).lower() == "instagram"]
155
+ profiles: list[dict[str, Any]] = []
156
+ for item in records:
157
+ if not isinstance(item, dict):
158
+ continue
159
+ platform = _clean(item.get("platform")).lower()
160
+ network = _clean(item.get("social_network")).lower()
161
+ url = _clean(item.get("url")).lower()
162
+ if platform == "instagram" or network == "instagram" or "instagram.com/" in url:
163
+ profiles.append(item)
164
+ return profiles
156
165
 
157
166
 
158
167
  def _characters(settings: Mapping[str, Any]) -> tuple[list[dict[str, Any]], Any | None]:
@@ -33,6 +33,8 @@ def create_channel(name: str, url: str = "", metadata: dict[str, Any] | None = N
33
33
  "google_account_email": "",
34
34
  "name": name.strip(),
35
35
  "url": url.strip(),
36
+ "platform": "youtube",
37
+ "social_network": "YouTube",
36
38
  "handle": "",
37
39
  "description": "",
38
40
  "description_source": "",
@@ -41,9 +43,15 @@ def create_channel(name: str, url: str = "", metadata: dict[str, Any] | None = N
41
43
  "thumbnail_url": "",
42
44
  "avatar_url": "",
43
45
  "subscriber_count": None,
46
+ "post_count": None,
47
+ "following_count": None,
44
48
  "video_count": None,
45
49
  "view_count": None,
46
50
  "metrics_source": "manual",
51
+ "public_lookup": False,
52
+ "last_public_lookup_at": None,
53
+ "country": "",
54
+ "character_id": "",
47
55
  "last_youtube_sync": None,
48
56
  "language": "Português",
49
57
  "blueprint_id": "",
@@ -48,6 +48,23 @@ def _meta(document: str, name: str) -> str:
48
48
  return ''
49
49
 
50
50
 
51
+ def _structured_metric(document: str, *keys: str) -> int | None:
52
+ """Read numeric Instagram counters embedded in the public HTML payload."""
53
+ for key in keys:
54
+ patterns = (
55
+ rf'"{re.escape(key)}"\s*:\s*\{{\s*"count"\s*:\s*(\d+)',
56
+ rf'"{re.escape(key)}"\s*:\s*(\d+)',
57
+ )
58
+ for pattern in patterns:
59
+ found = re.search(pattern, document, flags=re.IGNORECASE)
60
+ if found:
61
+ try:
62
+ return int(found.group(1))
63
+ except ValueError:
64
+ continue
65
+ return None
66
+
67
+
51
68
  def fetch_public_instagram_profile(source: str) -> IntegrationResult:
52
69
  try:
53
70
  reference = normalize_instagram_reference(source)
@@ -73,9 +90,9 @@ def fetch_public_instagram_profile(source: str) -> IntegrationResult:
73
90
  continue
74
91
  return None
75
92
 
76
- followers = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:followers|seguidores)',))
77
- following = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:following|seguindo)',))
78
- posts = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:posts|publicações|publications)',))
93
+ followers = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:followers|seguidores)',)) or _structured_metric(response.text, 'edge_followed_by', 'followers', 'follower_count')
94
+ following = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:following|seguindo)',)) or _structured_metric(response.text, 'edge_follow', 'following', 'following_count')
95
+ posts = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:posts|publicações|publications)',)) or _structured_metric(response.text, 'edge_owner_to_timeline_media', 'posts', 'post_count')
79
96
  data = {'id': f"instagram_{reference['username']}", **reference, 'name': title.split('(')[0].strip() or reference['username'], 'bio': description, 'avatar_url': avatar_url, 'subscriber_count': followers, 'following_count': following, 'post_count': posts, 'public_lookup': True, 'metrics_source': 'instagram_public_page', 'last_public_lookup_at': datetime.now(timezone.utc).isoformat()}
80
97
  return IntegrationResult(True, 'Perfil Instagram encontrado publicamente.', data)
81
98
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "license": "MIT",
6
6
  "main": "scripts/cli.mjs",