@danhachuel/thunderbolt 0.6.36 → 0.6.38

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,20 +152,28 @@ def _fetch_web_profile_user(username: str) -> dict[str, Any] | None:
152
152
  merged[key] = value
153
153
  return merged
154
154
 
155
+ request_headers = [
156
+ headers,
157
+ {**headers, 'User-Agent': 'Instagram 390.0.0.0.50 Android', 'Accept': 'application/json, text/plain, */*'},
158
+ {**headers, 'Referer': f'https://www.instagram.com/{username}/', 'Origin': 'https://www.instagram.com', 'X-Requested-With': 'XMLHttpRequest'},
159
+ ]
155
160
  best_user: dict[str, Any] | None = None
156
- for endpoint in endpoints:
157
- try:
158
- response = requests.get(endpoint, headers=headers, timeout=15)
159
- if response.status_code >= 400:
161
+ for request_header in request_headers:
162
+ for endpoint in endpoints:
163
+ try:
164
+ response = requests.get(endpoint, headers=request_header, timeout=15)
165
+ if response.status_code >= 400:
166
+ continue
167
+ payload = response.json()
168
+ except (requests.RequestException, ValueError, AttributeError, StopIteration):
169
+ if best_user:
170
+ return best_user
160
171
  continue
161
- payload = response.json()
162
- except (requests.RequestException, ValueError, AttributeError):
163
- continue
164
- user = ((payload.get('data') or {}).get('user') if isinstance(payload, dict) else None)
165
- if isinstance(user, dict):
166
- best_user = merge_profile(best_user, user)
167
- if profile_quality(best_user) >= 4:
168
- return best_user
172
+ user = ((payload.get('data') or {}).get('user') if isinstance(payload, dict) else None)
173
+ if isinstance(user, dict):
174
+ best_user = merge_profile(best_user, user)
175
+ if profile_quality(best_user) >= 4:
176
+ return best_user
169
177
 
170
178
  curl = shutil.which('curl')
171
179
  if curl:
@@ -188,6 +196,36 @@ def _fetch_web_profile_user(username: str) -> dict[str, Any] | None:
188
196
  return best_user
189
197
  except (OSError, subprocess.SubprocessError, ValueError):
190
198
  continue
199
+
200
+ # Em algumas instalações Windows o Instagram devolve a página HTML aos
201
+ # clientes HTTP, embora entregue o JSON completo a um navegador Chromium.
202
+ # O fallback é opcional: a aplicação continua funcional sem Playwright.
203
+ try:
204
+ from playwright.sync_api import sync_playwright
205
+ with sync_playwright() as playwright:
206
+ browser = playwright.chromium.launch(headless=True)
207
+ try:
208
+ page = browser.new_page(
209
+ user_agent=headers['User-Agent'],
210
+ extra_http_headers={'x-ig-app-id': headers['x-ig-app-id'], 'Accept-Language': 'en-US,en;q=0.9'},
211
+ )
212
+ for endpoint in endpoints:
213
+ try:
214
+ response = page.goto(endpoint, wait_until='domcontentloaded', timeout=30000)
215
+ if response is None or response.status >= 400:
216
+ continue
217
+ payload = json.loads(page.locator('body').inner_text(timeout=5000))
218
+ user = ((payload.get('data') or {}).get('user') if isinstance(payload, dict) else None)
219
+ if isinstance(user, dict):
220
+ best_user = merge_profile(best_user, user)
221
+ if profile_quality(best_user) >= 4:
222
+ return best_user
223
+ except (ValueError, TimeoutError):
224
+ continue
225
+ finally:
226
+ browser.close()
227
+ except (ImportError, OSError, RuntimeError):
228
+ pass
191
229
  return best_user
192
230
 
193
231
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.6.36",
3
+ "version": "0.6.38",
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",