@danhachuel/thunderbolt 0.7.36 → 0.7.37

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.
Files changed (2) hide show
  1. package/app/main.py +15 -19
  2. package/package.json +1 -1
package/app/main.py CHANGED
@@ -3176,7 +3176,7 @@ def render_channels():
3176
3176
  st.caption("Esta subaba usa a conta Google/YouTube seleccionada para listar os canais que ela gere. Não lê a caixa Gmail e não usa e-mails como pesquisa pública.")
3177
3177
  accounts = [account for account in settings.get("youtube_batch_accounts", []) if isinstance(account, dict) and account.get("id")]
3178
3178
  if not accounts:
3179
- st.info("Configure primeiro uma conta em Configurações > Configuração API > Contas Google/YouTube para canais em lote.")
3179
+ st.info("Nenhuma conta Google/YouTube disponível para a lista em lote; a lista permanece vazia.")
3180
3180
  else:
3181
3181
  account_ids = [str(account["id"]) for account in accounts]
3182
3182
  account_labels = {str(account["id"]): f"{account.get('email', 'Conta Google')} — {account.get('label', 'Canais YouTube')}" for account in accounts}
@@ -3953,9 +3953,7 @@ def render_new_video(page_title: str = "Criação de Vídeos", prefix: str = "ne
3953
3953
  with st.expander("Gerar Thumbnail com IA", expanded=False):
3954
3954
  topic_for_thumbnail = str(generation_settings.get("video_subject") or "").strip()
3955
3955
  if st.button("Gerar Thumbnail com IA", key=f"{prefix}_generate_creative", width="stretch"):
3956
- if selected_one is None:
3957
- st.error("Seleccione primeiro um canal.")
3958
- elif not topic_for_thumbnail:
3956
+ if not topic_for_thumbnail:
3959
3957
  st.error("Preencha o Video Subject antes de gerar a thumbnail.")
3960
3958
  else:
3961
3959
  try:
@@ -3963,7 +3961,7 @@ def render_new_video(page_title: str = "Criação de Vídeos", prefix: str = "ne
3963
3961
  existing_title = str(existing_payload.get("title") or topic_for_thumbnail).strip()
3964
3962
  generated = generate_thumbnail_variants_for_ui(
3965
3963
  read_json("settings.json", {}),
3966
- selected_one,
3964
+ selected_one or {},
3967
3965
  topic_for_thumbnail,
3968
3966
  same_channel_quantity,
3969
3967
  title=existing_title,
@@ -6166,8 +6164,7 @@ def render_tiktok_automation():
6166
6164
  channels = _tiktok_channel_records()
6167
6165
  prompt_ids, prompt_labels = _tiktok_prompt_options()
6168
6166
  if not channels:
6169
- st.info("Cadastre primeiro um canal TikTok.")
6170
- return
6167
+ st.info("Nenhum canal TikTok seleccionado. A lista de automação permanece vazia até existir um destino.")
6171
6168
  with st.expander("Canais cadastrados", expanded=False):
6172
6169
  for channel in channels:
6173
6170
  channel_id = str(channel["id"])
@@ -6426,8 +6423,7 @@ def render_facebook_automation() -> None:
6426
6423
  pages = _facebook_pages_for_automation()
6427
6424
  settings = read_json("settings.json", {})
6428
6425
  if not pages:
6429
- st.warning("Cadastre primeiro uma página em Canais e Perfis de Vídeos > Facebook Pages.")
6430
- return
6426
+ st.info("Nenhuma Facebook Page seleccionada. A fila pode ser criada e preenchida; o destino poderá ser escolhido mais tarde.")
6431
6427
  with st.expander("Configurar API Facebook da página", expanded=False):
6432
6428
  for page in pages:
6433
6429
  page_id = str(page.get("id") or "")
@@ -6440,9 +6436,9 @@ def render_facebook_automation() -> None:
6440
6436
  st.success("Credenciais da página guardadas localmente.")
6441
6437
  st.rerun()
6442
6438
  with st.form("facebook_automation_new_post"):
6443
- page_options = [str(page.get("id")) for page in pages]
6439
+ page_options = [""] + [str(page.get("id")) for page in pages]
6444
6440
  page_labels = {str(page.get("id")): str(page.get("name") or "Facebook Page") for page in pages}
6445
- selected_page = st.selectbox("Facebook Page", page_options, format_func=lambda value: page_labels.get(value, value))
6441
+ selected_page = st.selectbox("Facebook Page", page_options, format_func=lambda value: page_labels.get(value, "Nenhuma página seleccionada"), key="facebook_automation_target_page")
6446
6442
  form_cols = st.columns([2.2, 1, 1.3])
6447
6443
  with form_cols[0]:
6448
6444
  theme = st.text_input("Tema/ideia opcional", placeholder="Deixe vazio para o LLM sugerir um tema")
@@ -6452,7 +6448,7 @@ def render_facebook_automation() -> None:
6452
6448
  start_stage = st.selectbox("Iniciar por", ["Ideia / Tema", "Tema já definido"])
6453
6449
  create_clicked = st.form_submit_button("Criar post na fila", type="primary", width="stretch")
6454
6450
  if create_clicked:
6455
- page = next(page for page in pages if str(page.get("id")) == selected_page)
6451
+ page = next((page for page in pages if str(page.get("id")) == selected_page), {})
6456
6452
  post = create_post(page, image_count=int(image_count), theme=theme)
6457
6453
  if start_stage == "Tema já definido" and theme.strip():
6458
6454
  save_post({**post, "status": "artigo_pendente"})
@@ -7280,15 +7276,15 @@ def render_upload_destination_target(destination: str, channels: list[dict[str,
7280
7276
  select_label = "Canal" if destination == "YouTube" else ("Conta TikTok" if destination == "TikTok" else ("Conta Bilibili" if destination == "Bilibili" else "Perfil / página"))
7281
7277
  empty_label = "Nenhum canal YouTube cadastrado" if destination == "YouTube" else ("Nenhuma conta TikTok cadastrada" if destination == "TikTok" else ("Nenhuma conta Bilibili activa" if destination == "Bilibili" else f"Nenhum {destination} configurado"))
7282
7278
  if not options:
7283
- st.selectbox(select_label, [empty_label], disabled=True, key=f"upload_target_{destination_key}")
7279
+ st.selectbox(select_label, [""], format_func=lambda _value: empty_label, key=f"upload_target_{destination_key}")
7284
7280
  if destination == "YouTube":
7285
- st.caption("Cadastre ou liste pelo menos um canal YouTube antes de escolher o destino de envio.")
7281
+ st.caption("Nenhum canal YouTube disponível; o destino permanece vazio e pode ser escolhido mais tarde.")
7286
7282
  elif destination == "TikTok":
7287
- st.caption("Cadastre uma conta em Pipeline TikTok > Contas TikTok antes de escolher o destino de envio.")
7283
+ st.caption("Nenhuma conta TikTok disponível; o destino permanece vazio e pode ser escolhido mais tarde.")
7288
7284
  elif destination == "Bilibili":
7289
- st.caption("Configure e active uma conta em Configuração API > API Bilibili antes de escolher o destino de envio.")
7285
+ st.caption("Nenhuma conta Bilibili disponível; o destino permanece vazio e pode ser escolhido mais tarde.")
7290
7286
  else:
7291
- st.caption(f"A lista de {destination} será ligada numa etapa própria de credenciais/API.")
7287
+ st.caption(f"Nenhum destino {destination} disponível; a lista permanece vazia.")
7292
7288
  return None
7293
7289
  return st.selectbox(
7294
7290
  select_label,
@@ -7413,8 +7409,8 @@ def render_upload_conventional():
7413
7409
  quota_count = official_upload_count(channel, account)
7414
7410
  st.caption(f"API Oficial hoje: {quota_count}/{OFFICIAL_DAILY_LIMIT} envios nesta conta Gmail.")
7415
7411
  if not selected_youtube_channel:
7416
- st.caption("Seleccione primeiro um canal YouTube no selector acima para activar este envio.")
7417
- if st.button("Enviar pelo fluxo recomendado", type="primary", key=f"upload_youtube_{task['id']}", disabled=not selected_youtube_channel, help="Escolha o canal YouTube no selector acima." if not selected_youtube_channel else None):
7412
+ st.caption("Nenhum canal YouTube seleccionado; o destino permanece vazio e poderá ser escolhido mais tarde.")
7413
+ if st.button("Enviar pelo fluxo recomendado", type="primary", key=f"upload_youtube_{task['id']}"):
7418
7414
  tags = [tag.strip() for tag in tags_raw.split(",") if tag.strip()]
7419
7415
  result = upload_with_default_route(
7420
7416
  settings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.36",
3
+ "version": "0.7.37",
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",