@danhachuel/thunderbolt 0.6.25 → 0.6.27
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.
|
@@ -42,6 +42,12 @@ def _metric_input(value: Any) -> int | None:
|
|
|
42
42
|
return normalize_instagram_metric(value)
|
|
43
43
|
|
|
44
44
|
|
|
45
|
+
def _render_instagram_bio(value: Any) -> None:
|
|
46
|
+
bio = normalize_instagram_bio(value)
|
|
47
|
+
if bio:
|
|
48
|
+
st.markdown(bio.replace("\n", " \n"))
|
|
49
|
+
|
|
50
|
+
|
|
45
51
|
def _language_index(value: Any) -> int:
|
|
46
52
|
code = language_code(value)
|
|
47
53
|
return list(LANGUAGE_CODES).index(code) if code in LANGUAGE_CODES else list(LANGUAGE_CODES).index("pt")
|
|
@@ -326,9 +332,7 @@ def _render_instagram_card(profile: dict[str, Any], characters: list[dict[str, A
|
|
|
326
332
|
with header_cols[1]:
|
|
327
333
|
st.write(f"**{_clean(profile.get('name')) or 'Sem nome'}**")
|
|
328
334
|
st.caption(f"{_clean(profile.get('handle')) or _clean(profile.get('url')) or 'sem handler'}")
|
|
329
|
-
|
|
330
|
-
if bio:
|
|
331
|
-
st.caption(f"Bio: {bio}")
|
|
335
|
+
_render_instagram_bio(profile.get("bio"))
|
|
332
336
|
st.caption(f"{_clean(profile.get('country')) or 'País não definido'} · {_clean(profile.get('language')) or 'Idioma não definido'}")
|
|
333
337
|
with header_cols[2]:
|
|
334
338
|
st.metric("posts", _metric(profile.get("post_count")))
|
|
@@ -447,9 +451,7 @@ def render_social_networks(settings: dict[str, Any]) -> None:
|
|
|
447
451
|
with preview_cols[1]:
|
|
448
452
|
st.write(f"**{_clean(data.get('name')) or _clean(data.get('username'))}**")
|
|
449
453
|
st.caption(_clean(data.get("handle")))
|
|
450
|
-
|
|
451
|
-
if bio:
|
|
452
|
-
st.caption(f"Bio: {bio}")
|
|
454
|
+
_render_instagram_bio(data.get("bio"))
|
|
453
455
|
with preview_cols[2]:
|
|
454
456
|
st.metric("posts", _metric(data.get("post_count")))
|
|
455
457
|
with preview_cols[3]:
|
|
@@ -111,6 +111,23 @@ def _fetch_web_profile_user(username: str) -> dict[str, Any] | None:
|
|
|
111
111
|
f'https://www.instagram.com/api/v1/users/web_profile_info/?username={username}',
|
|
112
112
|
f'https://i.instagram.com/api/v1/users/web_profile_info/?username={username}',
|
|
113
113
|
)
|
|
114
|
+
curl = shutil.which('curl')
|
|
115
|
+
if curl:
|
|
116
|
+
for endpoint in endpoints:
|
|
117
|
+
try:
|
|
118
|
+
completed = subprocess.run(
|
|
119
|
+
[curl, '-L', '--max-time', '20', '-sS', '-A', headers['User-Agent'], '-H', f"x-ig-app-id: {headers['x-ig-app-id']}", '-H', 'Accept: application/json, text/plain, */*', endpoint],
|
|
120
|
+
capture_output=True,
|
|
121
|
+
text=True,
|
|
122
|
+
timeout=25,
|
|
123
|
+
check=False,
|
|
124
|
+
)
|
|
125
|
+
payload = json.loads(completed.stdout) if completed.returncode == 0 and completed.stdout else None
|
|
126
|
+
user = ((payload.get('data') or {}).get('user') if isinstance(payload, dict) else None)
|
|
127
|
+
if isinstance(user, dict):
|
|
128
|
+
return user
|
|
129
|
+
except (OSError, subprocess.SubprocessError, ValueError):
|
|
130
|
+
continue
|
|
114
131
|
for endpoint in endpoints:
|
|
115
132
|
try:
|
|
116
133
|
response = requests.get(endpoint, headers=headers, timeout=15)
|
|
@@ -122,22 +139,6 @@ def _fetch_web_profile_user(username: str) -> dict[str, Any] | None:
|
|
|
122
139
|
user = ((payload.get('data') or {}).get('user') if isinstance(payload, dict) else None)
|
|
123
140
|
if isinstance(user, dict):
|
|
124
141
|
return user
|
|
125
|
-
curl = shutil.which('curl')
|
|
126
|
-
if curl:
|
|
127
|
-
try:
|
|
128
|
-
completed = subprocess.run(
|
|
129
|
-
[curl, '-L', '--max-time', '20', '-sS', '-A', headers['User-Agent'], '-H', f"x-ig-app-id: {headers['x-ig-app-id']}", endpoint],
|
|
130
|
-
capture_output=True,
|
|
131
|
-
text=True,
|
|
132
|
-
timeout=25,
|
|
133
|
-
check=False,
|
|
134
|
-
)
|
|
135
|
-
payload = json.loads(completed.stdout) if completed.returncode == 0 and completed.stdout else None
|
|
136
|
-
user = ((payload.get('data') or {}).get('user') if isinstance(payload, dict) else None)
|
|
137
|
-
if isinstance(user, dict):
|
|
138
|
-
return user
|
|
139
|
-
except (OSError, subprocess.SubprocessError, ValueError):
|
|
140
|
-
pass
|
|
141
142
|
return None
|
|
142
143
|
|
|
143
144
|
|
|
@@ -156,6 +157,7 @@ def _profile_data_from_api(user: Mapping[str, Any], reference: Mapping[str, str]
|
|
|
156
157
|
'subscriber_count': followers,
|
|
157
158
|
'following_count': following,
|
|
158
159
|
'post_count': media,
|
|
160
|
+
'is_private': bool(user.get('is_private')),
|
|
159
161
|
'public_lookup': True,
|
|
160
162
|
'metrics_source': 'instagram_web_profile_info',
|
|
161
163
|
'last_public_lookup_at': datetime.now(timezone.utc).isoformat(),
|
|
@@ -289,6 +291,8 @@ def fetch_public_instagram_posts(source: str, limit: int = 10) -> IntegrationRes
|
|
|
289
291
|
api_posts.append(post)
|
|
290
292
|
if api_posts:
|
|
291
293
|
return IntegrationResult(True, 'Posts públicos encontrados.', reference | {'posts': api_posts[:max(1, int(limit))]})
|
|
294
|
+
if api_user.get('is_private'):
|
|
295
|
+
return IntegrationResult(False, 'Esta conta é privada. O Instagram não disponibiliza posts sem uma sessão autenticada.', reference | {'posts': [], 'is_private': True})
|
|
292
296
|
try:
|
|
293
297
|
response = requests.get(reference['url'], headers={'User-Agent': 'Mozilla/5.0', 'Accept-Language': 'pt-BR,pt;q=0.9,en;q=0.8'}, timeout=15)
|
|
294
298
|
except requests.RequestException as exc:
|
package/package.json
CHANGED