@danhachuel/thunderbolt 0.5.87 → 0.5.88

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.
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import hashlib
4
+ import errno
4
5
  import json
5
6
  import os
6
7
  import re
@@ -46,6 +47,14 @@ def _authorization_error_message(email: str, exc: Exception) -> str:
46
47
  return f"A autorização da conta {email} falhou: {detail}"
47
48
 
48
49
 
50
+ def _is_address_in_use_error(exc: BaseException) -> bool:
51
+ """Return whether an OAuth callback bind failed because its port is busy."""
52
+ if getattr(exc, "winerror", None) == 10048 or getattr(exc, "errno", None) == errno.EADDRINUSE:
53
+ return True
54
+ detail = str(exc).lower()
55
+ return "10048" in detail or "address already in use" in detail or "only one usage" in detail
56
+
57
+
49
58
  def _text(value: Any) -> str:
50
59
  return str(value or "").strip()
51
60
 
@@ -115,15 +124,26 @@ def authorize_account(account: dict[str, Any], storage_root: Path, *, open_brows
115
124
  except ImportError as exc:
116
125
  return IntegrationResult(False, "As dependências Google OAuth ainda não estão instaladas. Execute a instalação do Thunderbolt novamente.", {"status": "missing_dependencies", "error": str(exc)})
117
126
  try:
118
- flow = InstalledAppFlow.from_client_config(_client_config(account), BATCH_SCOPES)
119
- credentials = flow.run_local_server(
120
- host=loopback_host(),
121
- port=loopback_port(),
122
- open_browser=open_browser,
123
- access_type="offline",
124
- prompt="consent",
125
- include_granted_scopes="true",
126
- )
127
+ credentials = None
128
+ configured_port = loopback_port()
129
+ for attempt, port in enumerate((configured_port, 0)):
130
+ flow = InstalledAppFlow.from_client_config(_client_config(account), BATCH_SCOPES)
131
+ try:
132
+ credentials = flow.run_local_server(
133
+ host=loopback_host(),
134
+ port=port,
135
+ open_browser=open_browser,
136
+ access_type="offline",
137
+ prompt="consent",
138
+ include_granted_scopes="true",
139
+ )
140
+ break
141
+ except OSError as exc:
142
+ if attempt == 0 and _is_address_in_use_error(exc):
143
+ continue
144
+ raise
145
+ if credentials is None:
146
+ raise RuntimeError("Não foi possível iniciar o callback OAuth local.")
127
147
  path = token_path(storage_root, account)
128
148
  _save_credentials(path, credentials)
129
149
  return IntegrationResult(True, f"Conta Google autorizada para listagem de canais: {email}.", {"status": "authorized", "email": email, "token_path": str(path)})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.5.87",
3
+ "version": "0.5.88",
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",