@danhachuel/thunderbolt 0.5.92 → 0.5.94

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.
package/app/main.py CHANGED
@@ -124,6 +124,7 @@ from integrations.youtube_direct_credentials import delete_credentials_document,
124
124
  from integrations.session_info_health import check_account_session_info_health
125
125
  from integrations.youtube_session_manager import renew_account_session
126
126
  from integrations.youtube_batch import account_key as youtube_batch_account_key, account_status as youtube_batch_account_status, authorize_account as authorize_youtube_batch_account, delete_account_token as delete_youtube_batch_token, list_my_channels as list_youtube_batch_channels, loopback_redirect_uri
127
+ from integrations.youtube_growth_api import find_account_for_channel as find_youtube_growth_account
127
128
  from integrations.local_runtime import MoneyPrinterRuntime
128
129
  from integrations.moneyprinter_config import sync_moneyprinter_config
129
130
  from integrations.openai_model_discovery import DEFAULT_NVIDIA_NIM_BASE_URL
@@ -1496,21 +1497,6 @@ def render_growth_youtube():
1496
1497
  st.caption("Auditoria pública baseada nos 3 pilares críticos e nas métricas secundárias do agente Growth.")
1497
1498
  growth_settings = read_json("settings.json", {})
1498
1499
  youtube_data_api_ready = bool(str(growth_settings.get("youtube_api_key") or os.getenv("YOUTUBE_API_KEY") or "").strip())
1499
- growth_accounts = growth_settings.get("youtube_batch_accounts", [])
1500
- analytics_accounts_ready = False
1501
- if isinstance(growth_accounts, list):
1502
- for growth_account in growth_accounts:
1503
- if isinstance(growth_account, dict) and youtube_batch_account_status(growth_account, STORAGE).ok:
1504
- analytics_accounts_ready = True
1505
- break
1506
- st.markdown("**Estado das APIs de Growth**")
1507
- api_status_cols = st.columns(2, gap="small")
1508
- with api_status_cols[0]:
1509
- st.caption("YouTube Data API v3: Metadados públicos")
1510
- _api_status_badge("Configured" if youtube_data_api_ready else "Missing configuration", "ready" if youtube_data_api_ready else "missing")
1511
- with api_status_cols[1]:
1512
- st.caption("YouTube Analytics API: Métricas internas")
1513
- _api_status_badge("Configured" if analytics_accounts_ready else "Missing configuration", "ready" if analytics_accounts_ready else "missing")
1514
1500
  channels = [item for item in read_json("channels.json", []) if isinstance(item, dict) and item.get("active", True) and is_youtube_channel_record(item)]
1515
1501
  if not channels:
1516
1502
  st.info("Cadastre pelo menos um canal YouTube em Canais YouTube para iniciar a análise.")
@@ -1526,6 +1512,16 @@ def render_growth_youtube():
1526
1512
  with action_status_col:
1527
1513
  if st.session_state.get("growth_analysis_status") == "complete":
1528
1514
  st.markdown('<div style="padding-top:9px;color:#22c55e;font-weight:700;white-space:nowrap;">✓ Análise concluída</div>', unsafe_allow_html=True)
1515
+ matched_growth_account = find_youtube_growth_account(selected, growth_settings)
1516
+ analytics_accounts_ready = bool(matched_growth_account and youtube_batch_account_status(matched_growth_account, STORAGE).ok)
1517
+ st.markdown("**Estado das APIs de Growth**")
1518
+ api_status_cols = st.columns(2, gap="small")
1519
+ with api_status_cols[0]:
1520
+ st.caption("YouTube Data API v3: Metadados públicos")
1521
+ _api_status_badge("Configured" if youtube_data_api_ready else "Missing configuration", "ready" if youtube_data_api_ready else "missing")
1522
+ with api_status_cols[1]:
1523
+ st.caption("YouTube Analytics API: Métricas internas")
1524
+ _api_status_badge("Configured" if analytics_accounts_ready else "Missing configuration", "ready" if analytics_accounts_ready else "missing")
1529
1525
  if analyse_clicked:
1530
1526
  settings = read_json("settings.json", {})
1531
1527
  llm_settings, _ = ensure_llm_provider_cards(settings)
@@ -8341,17 +8337,15 @@ def render_notifications():
8341
8337
 
8342
8338
 
8343
8339
  def render_models_ai_tutorial():
8344
- tutorial_url = "https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-instagram.md"
8345
8340
  tutorial_path = ROOT / "seed" / "references" / "guide-instagram.md"
8346
8341
  st.title("Tutorial Meta")
8347
8342
  st.caption("Guia de configuração de uma conta Instagram profissional e das credenciais Meta para automações com n8n.")
8348
- st.markdown(f"[Abrir fonte original no GitHub]({tutorial_url})")
8349
8343
  try:
8350
8344
  tutorial_content = tutorial_path.read_text(encoding="utf-8").strip()
8351
8345
  except OSError:
8352
8346
  tutorial_content = ""
8353
8347
  if not tutorial_content:
8354
- st.error("O conteúdo local do tutorial não está disponível. Consulte a fonte original no GitHub.")
8348
+ st.error("O conteúdo local do tutorial não está disponível.")
8355
8349
  return
8356
8350
  st.markdown(tutorial_content, unsafe_allow_html=True)
8357
8351
 
@@ -8363,18 +8357,16 @@ def render_niche_tutorial(tutorial_kind: str):
8363
8357
 
8364
8358
 
8365
8359
  def render_supabase_tutorial():
8366
- tutorial_url = "https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-supabase.md"
8367
8360
  tutorial_path = ROOT / "seed" / "references" / "guide-supabase.md"
8368
8361
  ui_language = current_ui_language()
8369
8362
  st.title(ui_text("Tutorial Supabase", ui_language))
8370
8363
  st.caption(ui_text("Guia de configuração do Supabase para automações com n8n.", ui_language))
8371
- st.markdown(f"[Abrir fonte original no GitHub]({tutorial_url})")
8372
8364
  try:
8373
8365
  tutorial_content = tutorial_path.read_text(encoding="utf-8").strip()
8374
8366
  except OSError:
8375
8367
  tutorial_content = ""
8376
8368
  if not tutorial_content:
8377
- st.error("O conteúdo local do tutorial não está disponível. Consulte a fonte original no GitHub.")
8369
+ st.error("O conteúdo local do tutorial não está disponível.")
8378
8370
  return
8379
8371
  st.markdown(tutorial_content, unsafe_allow_html=True)
8380
8372
 
@@ -8384,13 +8376,12 @@ def render_google_oauth_tutorial():
8384
8376
  tutorial_path = ROOT / "seed" / "references" / "tutorial-oauth-google.md"
8385
8377
  st.title("Tutorial OAuth do Google")
8386
8378
  st.caption("Guia completo para configurar a autenticação OAuth do Google e o acesso à YouTube Data API v3.")
8387
- st.markdown("[Abrir Google Cloud Console](https://console.cloud.google.com/)")
8388
8379
  try:
8389
8380
  tutorial_content = tutorial_path.read_text(encoding="utf-8").strip()
8390
8381
  except OSError:
8391
8382
  tutorial_content = ""
8392
8383
  if not tutorial_content:
8393
- st.error("O conteúdo local do tutorial não está disponível. Consulte a documentação OAuth do Google.")
8384
+ st.error("O conteúdo local do tutorial não está disponível.")
8394
8385
  return
8395
8386
  st.markdown(tutorial_content, unsafe_allow_html=False)
8396
8387
 
@@ -8400,13 +8391,12 @@ def render_youtube_frontend_upload_tutorial():
8400
8391
  tutorial_path = ROOT / "seed" / "references" / "youtube-video-upload-frontend.md"
8401
8392
  st.title("Tutorial YouTube Video-Upload Frontend")
8402
8393
  st.caption("Guia prático e seguro para rever metadados, sessão e envio directo de vídeos concluídos.")
8403
- st.markdown("[Abrir referência técnica no GitHub](https://github.com/Nojus10/YouTube-Video-Upload-Frontend-Api)")
8404
8394
  try:
8405
8395
  tutorial_content = tutorial_path.read_text(encoding="utf-8").strip()
8406
8396
  except OSError:
8407
8397
  tutorial_content = ""
8408
8398
  if not tutorial_content:
8409
- st.error("O conteúdo local do tutorial não está disponível. Consulte a referência técnica no GitHub.")
8399
+ st.error("O conteúdo local do tutorial não está disponível.")
8410
8400
  return
8411
8401
  st.markdown(tutorial_content, unsafe_allow_html=False)
8412
8402
 
@@ -8416,13 +8406,12 @@ def render_youtube_data_api_key_tutorial():
8416
8406
  tutorial_path = ROOT / "seed" / "references" / "tutorial-youtube-data-api-key.md"
8417
8407
  st.title("Tutorial YouTube Data API Key (Public Data)")
8418
8408
  st.caption("Guia para criar e configurar uma YouTube Data API Key para consultas de dados públicos.")
8419
- st.markdown("[Abrir documento fonte no Google Drive](https://drive.google.com/file/d/1ypzaR1v8khBxyUQmZ12ZAY0pGTD49mqt/view)")
8420
8409
  try:
8421
8410
  tutorial_content = tutorial_path.read_text(encoding="utf-8").strip()
8422
8411
  except OSError:
8423
8412
  tutorial_content = ""
8424
8413
  if not tutorial_content:
8425
- st.error("O conteúdo local do tutorial não está disponível. Consulte o documento fonte no Google Drive.")
8414
+ st.error("O conteúdo local do tutorial não está disponível.")
8426
8415
  return
8427
8416
  st.markdown(tutorial_content, unsafe_allow_html=False)
8428
8417
 
@@ -23,9 +23,9 @@ def find_account_for_channel(channel: Mapping[str, Any], settings: Mapping[str,
23
23
  channel_id = _text(channel.get("youtube_channel_id") or channel.get("id"))
24
24
  account_id = _text(channel.get("google_account_id"))
25
25
  accounts = _accounts(settings)
26
+ if account_id:
27
+ return next((account for account in accounts if _text(account.get("id")) == account_id), None)
26
28
  for account in accounts:
27
- if account_id and _text(account.get("id")) == account_id:
28
- return account
29
29
  known_channels = account.get("channels", [])
30
30
  if isinstance(known_channels, list) and any(_text(item.get("youtube_channel_id") or item.get("id")) == channel_id for item in known_channels if isinstance(item, Mapping)):
31
31
  return account
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.5.92",
3
+ "version": "0.5.94",
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",
@@ -171,5 +171,3 @@ You'll see this interface below.
171
171
  2. The Instagram account id which you'll need to set in the `Configure` node in the n8n workflow
172
172
 
173
173
  ---
174
-
175
- > **Source:** [ai_agents_az/episode_8/guide-instagram.md](https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-instagram.md)
@@ -65,5 +65,3 @@ No Thunderbolt, abra **Configurações > Configuração API > AI Influencers > B
65
65
  O Thunderbolt usa o Supabase como backend seleccionado, não como executor de n8n: os assets são enviados ao Storage, os metadados ficam nas tabelas e os estados de geração ficam em `influencer_content`. Para uma execução totalmente local, seleccione **SQLite** no mesmo painel; a alternativa cria `storage/state/ai_influencers.db` e não utiliza a conta Supabase.
66
66
 
67
67
  A conta Supabase está pronta para ser utilizada pela automação.
68
-
69
- Fonte original: [guide-supabase.md no GitHub](https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-supabase.md)
@@ -1,9 +1,5 @@
1
- # Tutorial YouTube Data API Key (Public Data)
2
-
3
1
  Este tutorial explica como criar uma **YouTube Data API Key** no Google Cloud e configurá-la no Thunderbolt para consultar dados públicos do YouTube, como vídeos, canais e estatísticas públicas.
4
2
 
5
- > **Fonte:** [Tutorial YouTube Data API Key (Public Data) no Google Drive](https://drive.google.com/file/d/1ypzaR1v8khBxyUQmZ12ZAY0pGTD49mqt/view)
6
-
7
3
  ## Quando usar uma API Key
8
4
 
9
5
  Uma API Key é suficiente para operações com dados públicos, como pesquisar vídeos, consultar canais públicos e obter estatísticas públicas. Ela **não concede acesso a dados privados** da conta nem substitui o OAuth 2.0 para playlists privadas, inscrições privadas ou uploads.
@@ -93,4 +89,3 @@ Uma API Key só identifica o projecto e permite chamadas autorizadas para dados
93
89
  - [Google Cloud Console](https://console.cloud.google.com/)
94
90
  - [YouTube Data API v3](https://developers.google.com/youtube/v3)
95
91
  - [Documentação de quotas da YouTube Data API](https://developers.google.com/youtube/v3/determine_quota_cost)
96
- - [Documento fonte no Google Drive](https://drive.google.com/file/d/1ypzaR1v8khBxyUQmZ12ZAY0pGTD49mqt/view)
@@ -42,7 +42,3 @@ Depois de confirmar o canal, a privacidade e os metadados, seleccione o fluxo de
42
42
  | Falha de rede | Não repita automaticamente sem confirmar se o vídeo foi criado no YouTube Studio. |
43
43
  | Metadados incompletos | Corrija título, descrição, tags, idioma ou privacidade no formulário antes de enviar. |
44
44
  | Limite ou política da plataforma | Pare o processo e siga as políticas e limites actualmente aplicáveis do YouTube. |
45
-
46
- ## Referência técnica
47
-
48
- O material fornecido pelo utilizador cita o repositório [Nojus10/YouTube-Video-Upload-Frontend-Api](https://github.com/Nojus10/YouTube-Video-Upload-Frontend-Api). O Thunderbolt apresenta este tutorial como orientação de integração segura; não replica segredos, valores de autenticação nem instruções de extracção de credenciais.