@danhachuel/thunderbolt 0.6.63 → 0.6.64

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.
@@ -194,6 +194,8 @@ def _render_instagram_posts(profile: Mapping[str, Any]) -> None:
194
194
  if load_clicked or refresh_clicked:
195
195
  target = max(10, len(posts)) if refresh_clicked else 10
196
196
  posts_ok, posts_message, loaded_posts = _load_instagram_posts(profile, limit=target)
197
+ st.write(f"Resultado do posts: {posts_ok}, mensagem: {posts_message}")
198
+ st.write(f"Posts retornados: {len(loaded_posts)}")
197
199
  if posts_ok:
198
200
  posts = loaded_posts
199
201
  _persist_instagram_posts(profile, posts)
@@ -221,6 +223,8 @@ def _render_instagram_posts(profile: Mapping[str, Any]) -> None:
221
223
  if posts_ok:
222
224
  _persist_instagram_posts(profile, loaded_posts)
223
225
  st.rerun()
226
+ st.write(f"Resultado do posts: {posts_ok}, mensagem: {posts_message}")
227
+ st.write(f"Posts retornados: {len(loaded_posts)}")
224
228
  st.warning(posts_message)
225
229
 
226
230
 
@@ -52,14 +52,10 @@ def _fetch_instagram_html_with_playwright(url: str, username: str) -> str:
52
52
  extra_http_headers={'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7'},
53
53
  )
54
54
  page = context.new_page()
55
- response = page.goto(url, wait_until='domcontentloaded', timeout=30000)
55
+ response = page.goto(url, wait_until='networkidle', timeout=30000)
56
56
  status = response.status if response else None
57
57
  print(f'Playwright usado no Windows para @{username}; status HTML={status}')
58
- page.wait_for_timeout(5000)
59
- try:
60
- page.wait_for_load_state('networkidle', timeout=10000)
61
- except (PlaywrightTimeoutError, TimeoutError):
62
- pass
58
+ page.wait_for_timeout(3000)
63
59
  html_content = page.content()
64
60
  print(f'HTML Instagram recebido no Windows para @{username}: {len(html_content)} bytes')
65
61
  return html_content
@@ -152,16 +148,30 @@ def _structured_metric_from_json(document: str, *keys: str) -> int | None:
152
148
  def _extract_posts_from_html(document: str, limit: int = 10) -> list[dict[str, Any]]:
153
149
  posts: list[dict[str, Any]] = []
154
150
  seen: set[str] = set()
151
+ wanted_limit = max(1, int(limit))
152
+
153
+ def add_node(node: Any) -> bool:
154
+ if not isinstance(node, dict):
155
+ return False
156
+ post = _post_from_node(node)
157
+ if not post or post['id'] in seen:
158
+ return False
159
+ seen.add(post['id'])
160
+ posts.append(post)
161
+ return len(posts) >= wanted_limit
162
+
155
163
  for payload in _embedded_json_documents(document):
156
164
  for node in _walk_json(payload):
157
165
  if not isinstance(node, dict):
158
166
  continue
159
- post = _post_from_node(node)
160
- if not post or post['id'] in seen:
161
- continue
162
- seen.add(post['id'])
163
- posts.append(post)
164
- if len(posts) >= max(1, int(limit)):
167
+ media = node.get('edge_owner_to_timeline_media')
168
+ if isinstance(media, Mapping):
169
+ edges = media.get('edges') or media.get('items') or []
170
+ for edge in edges:
171
+ candidate = edge.get('node') if isinstance(edge, dict) else edge
172
+ if add_node(candidate):
173
+ return posts
174
+ if add_node(node):
165
175
  return posts
166
176
  return posts
167
177
 
@@ -599,6 +609,15 @@ def fetch_public_instagram_posts(source: str, limit: int = 10) -> IntegrationRes
599
609
  if platform.system() == 'Windows':
600
610
  html_content = _fetch_instagram_html_with_playwright(reference['url'], reference['username'])
601
611
  posts = _extract_posts_from_html(html_content, limit) if html_content else []
612
+ print(f'Posts extraídos no Windows para @{reference["username"]}: {len(posts)}')
613
+ if not posts and html_content:
614
+ try:
615
+ os.makedirs('storage', exist_ok=True)
616
+ with open('storage/debug_posts.html', 'w', encoding='utf-8', errors='replace') as debug_file:
617
+ debug_file.write(html_content)
618
+ print(f'HTML de debug dos posts guardado em storage/debug_posts.html para @{reference["username"]}')
619
+ except OSError as exc:
620
+ print(f'Não foi possível guardar storage/debug_posts.html: {exc}')
602
621
  return IntegrationResult(bool(posts), 'Posts públicos encontrados.' if posts else 'Não foi possível encontrar posts públicos nesta página do Instagram.', reference | {'posts': posts[:max(1, int(limit))]})
603
622
  try:
604
623
  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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.6.63",
3
+ "version": "0.6.64",
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",