@danhachuel/thunderbolt 0.6.16 → 0.6.17

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.
@@ -8,6 +8,7 @@ import streamlit as st
8
8
  from hermes_ui.domain import create_channel, update_channel
9
9
  from hermes_ui.influencers import InfluencerBackendError, STANDALONE_CONTENT_INFLUENCER_ID, get_repository
10
10
  from hermes_ui.storage import read_json, write_json
11
+ from hermes_ui.languages import LANGUAGE_CODES, language_code, language_label
11
12
  from integrations.instagram_public import fetch_public_instagram_profile
12
13
  from integrations.meta_social import test_facebook_pages_api_card, test_instagram_api_card
13
14
 
@@ -25,6 +26,11 @@ def _metric(value: Any) -> str:
25
26
  return _clean(value) or "—"
26
27
 
27
28
 
29
+ def _language_index(value: Any) -> int:
30
+ code = language_code(value)
31
+ return list(LANGUAGE_CODES).index(code) if code in LANGUAGE_CODES else list(LANGUAGE_CODES).index("pt")
32
+
33
+
28
34
  def _api_card_defaults(kind: str) -> tuple[str, list[str], Callable[[Mapping[str, Any]], dict[str, Any]]]:
29
35
  if kind == "instagram":
30
36
  return "instagram_api_cards", ["id", "label", "account_id", "access_token"], test_instagram_api_card
@@ -240,14 +246,14 @@ def _render_instagram_card(profile: dict[str, Any], characters: list[dict[str, A
240
246
  name = st.text_input("Nome", value=_clean(profile.get("name")), key=f"instagram_edit_name_{profile_id}")
241
247
  handle = st.text_input("handler", value=_clean(profile.get("handle")), key=f"instagram_edit_handle_{profile_id}")
242
248
  country = st.text_input("País", value=_clean(profile.get("country")), key=f"instagram_edit_country_{profile_id}")
243
- language = st.text_input("Idioma", value=_clean(profile.get("language")), key=f"instagram_edit_language_{profile_id}")
249
+ language = st.selectbox("Idioma", list(LANGUAGE_CODES), index=_language_index(profile.get("language")), format_func=language_label, key=f"instagram_edit_language_{profile_id}")
244
250
  with edit_cols[1]:
245
251
  posts = st.number_input("posts", min_value=0, value=int(profile.get("post_count") or 0), key=f"instagram_edit_posts_{profile_id}")
246
252
  followers = st.number_input("Seguidores", min_value=0, value=int(profile.get("subscriber_count") or 0), key=f"instagram_edit_followers_{profile_id}")
247
253
  following = st.number_input("seguindo", min_value=0, value=int(profile.get("following_count") or 0), key=f"instagram_edit_following_{profile_id}")
248
254
  save_edit = st.form_submit_button("Guardar alterações", type="primary", use_container_width=True)
249
255
  if save_edit:
250
- update_channel(profile_id, {"name": name.strip(), "handle": handle.strip(), "country": country.strip(), "language": language.strip(), "post_count": int(posts), "subscriber_count": int(followers), "following_count": int(following)})
256
+ update_channel(profile_id, {"name": name.strip(), "handle": handle.strip(), "country": country.strip(), "language": language, "post_count": int(posts), "subscriber_count": int(followers), "following_count": int(following)})
251
257
  st.session_state.pop(edit_key, None)
252
258
  st.success("Conta Instagram actualizada.")
253
259
  st.rerun()
@@ -317,7 +323,7 @@ def render_social_networks(settings: dict[str, Any]) -> None:
317
323
  with form_cols[0]:
318
324
  name = st.text_input("Nome", value=_clean(data.get("name")), key="social_instagram_result_name")
319
325
  country = st.text_input("País", value=_clean(data.get("country")), key="social_instagram_result_country")
320
- language = st.text_input("Idioma", value=_clean(data.get("language")), key="social_instagram_result_language")
326
+ language = st.selectbox("Idioma", list(LANGUAGE_CODES), index=_language_index(data.get("language")), format_func=language_label, key="social_instagram_result_language")
321
327
  with form_cols[1]:
322
328
  posts = st.number_input("posts", min_value=0, value=int(data.get("post_count") or 0), key="social_instagram_result_posts")
323
329
  followers = st.number_input("Seguidores", min_value=0, value=int(data.get("subscriber_count") or 0), key="social_instagram_result_followers")
@@ -50,10 +50,11 @@ def _meta(document: str, name: str) -> str:
50
50
 
51
51
  def _structured_metric(document: str, *keys: str) -> int | None:
52
52
  """Read numeric Instagram counters embedded in the public HTML payload."""
53
+ document = unescape(document)
53
54
  for key in keys:
54
55
  patterns = (
55
- rf'"{re.escape(key)}"\s*:\s*\{{\s*"count"\s*:\s*(\d+)',
56
- rf'"{re.escape(key)}"\s*:\s*(\d+)',
56
+ rf'\\?["\']{re.escape(key)}\\?["\']\s*:\s*\{{[^}}]{{0,240}}?\\?["\']count\\?["\']\s*:\s*(\d+)',
57
+ rf'\\?["\']{re.escape(key)}\\?["\']\s*:\s*(\d+)',
57
58
  )
58
59
  for pattern in patterns:
59
60
  found = re.search(pattern, document, flags=re.IGNORECASE)
@@ -91,7 +92,7 @@ def fetch_public_instagram_profile(source: str) -> IntegrationResult:
91
92
  return None
92
93
 
93
94
  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
+ following = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:following|seguindo)',)) or _structured_metric(response.text, 'edge_follow', 'follows', 'following', 'following_count', 'followingCount')
95
96
  posts = metric((r'([\d,.]+)\s*(?:mil\s+)?(?:posts|publicações|publications)',)) or _structured_metric(response.text, 'edge_owner_to_timeline_media', 'posts', 'post_count')
96
97
  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()}
97
98
  return IntegrationResult(True, 'Perfil Instagram encontrado publicamente.', data)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.6.16",
3
+ "version": "0.6.17",
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",