@danhachuel/thunderbolt 0.6.19 → 0.6.20
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.
|
@@ -29,6 +29,14 @@ def _metric(value: Any) -> str:
|
|
|
29
29
|
return _clean(value) or "—"
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def _profile_metric(profile: Mapping[str, Any], *keys: str) -> Any:
|
|
33
|
+
for key in keys:
|
|
34
|
+
value = profile.get(key)
|
|
35
|
+
if value not in (None, ""):
|
|
36
|
+
return value
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
|
|
32
40
|
def _language_index(value: Any) -> int:
|
|
33
41
|
code = language_code(value)
|
|
34
42
|
return list(LANGUAGE_CODES).index(code) if code in LANGUAGE_CODES else list(LANGUAGE_CODES).index("pt")
|
|
@@ -297,16 +305,20 @@ def _render_instagram_card(profile: dict[str, Any], characters: list[dict[str, A
|
|
|
297
305
|
with header_cols[2]:
|
|
298
306
|
st.metric("posts", _metric(profile.get("post_count")))
|
|
299
307
|
with header_cols[3]:
|
|
300
|
-
st.metric("Seguidores", _metric(profile
|
|
308
|
+
st.metric("Seguidores", _metric(_profile_metric(profile, "subscriber_count", "followers_count", "follower_count")))
|
|
301
309
|
with header_cols[4]:
|
|
302
|
-
st.metric("seguindo", _metric(profile
|
|
310
|
+
st.metric("seguindo", _metric(_profile_metric(profile, "following_count", "following", "follows")))
|
|
303
311
|
with header_cols[5]:
|
|
304
312
|
refresh_col, edit_col = st.columns(2)
|
|
305
313
|
with refresh_col:
|
|
306
314
|
if st.button("↻", help="Actualizar posts, seguidores e seguindo", key=f"refresh_instagram_{profile_id}"):
|
|
307
315
|
result = fetch_public_instagram_profile(_clean(profile.get("url")) or _clean(profile.get("handle")))
|
|
308
316
|
if result.ok:
|
|
309
|
-
|
|
317
|
+
refreshed = dict(result.data)
|
|
318
|
+
for field in ("subscriber_count", "following_count", "post_count", "bio", "avatar_url"):
|
|
319
|
+
if refreshed.get(field) in (None, "") and profile.get(field) not in (None, ""):
|
|
320
|
+
refreshed[field] = profile[field]
|
|
321
|
+
update_channel(profile_id, {**refreshed, "platform": "instagram", "country": profile.get("country", ""), "language": profile.get("language", ""), "character_id": profile.get("character_id", "")})
|
|
310
322
|
st.success("Métricas Instagram actualizadas.")
|
|
311
323
|
st.rerun()
|
|
312
324
|
st.warning(result.message)
|
|
@@ -67,6 +67,24 @@ def _structured_metric(document: str, *keys: str) -> int | None:
|
|
|
67
67
|
return None
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
def _structured_metric_from_json(document: str, *keys: str) -> int | None:
|
|
71
|
+
wanted = {key.casefold() for key in keys}
|
|
72
|
+
for parsed in _embedded_json_documents(document):
|
|
73
|
+
for node in _walk_json(parsed):
|
|
74
|
+
if not isinstance(node, dict):
|
|
75
|
+
continue
|
|
76
|
+
for key, value in node.items():
|
|
77
|
+
if str(key).casefold() not in wanted:
|
|
78
|
+
continue
|
|
79
|
+
if isinstance(value, dict):
|
|
80
|
+
value = value.get('count') or value.get('value')
|
|
81
|
+
try:
|
|
82
|
+
return int(value)
|
|
83
|
+
except (TypeError, ValueError):
|
|
84
|
+
continue
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
|
|
70
88
|
def fetch_public_instagram_profile(source: str) -> IntegrationResult:
|
|
71
89
|
try:
|
|
72
90
|
reference = normalize_instagram_reference(source)
|
|
@@ -92,8 +110,8 @@ def fetch_public_instagram_profile(source: str) -> IntegrationResult:
|
|
|
92
110
|
continue
|
|
93
111
|
return None
|
|
94
112
|
|
|
95
|
-
followers = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:followers|seguidores)',)) or _structured_metric(response.text, 'edge_followed_by', 'followers', 'follower_count')
|
|
96
|
-
following = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:following|seguindo)',)) or _structured_metric(response.text, 'edge_follow', 'follows', 'following', 'following_count', 'followingCount')
|
|
113
|
+
followers = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:followers|seguidores)',)) or _structured_metric(response.text, 'edge_followed_by', 'followers', 'follower_count') or _structured_metric_from_json(response.text, 'edge_followed_by', 'followers', 'follower_count', 'followerCount')
|
|
114
|
+
following = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:following|seguindo)',)) or _structured_metric(response.text, 'edge_follow', 'follows', 'following', 'following_count', 'followingCount') or _structured_metric_from_json(response.text, 'edge_follow', 'follows', 'following', 'following_count', 'followingCount')
|
|
97
115
|
posts = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:posts|publicações|publications)',)) or _structured_metric(response.text, 'edge_owner_to_timeline_media', 'posts', 'post_count')
|
|
98
116
|
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()}
|
|
99
117
|
return IntegrationResult(True, 'Perfil Instagram encontrado publicamente.', data)
|
package/package.json
CHANGED