@danhachuel/thunderbolt 0.7.10 → 0.7.12

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
@@ -2626,7 +2626,16 @@ def _channel_average_video_time(channel: dict[str, Any], *, prompt_master: str =
2626
2626
 
2627
2627
  def _refresh_youtube_channel_metrics(channel: dict[str, Any], youtube: YouTubeAdapter) -> tuple[bool, str]:
2628
2628
  channel_ref = str(channel.get("youtube_channel_id") or channel.get("youtube_id") or channel.get("url") or channel.get("handle") or "")
2629
- result = youtube.fetch_channel(channel_ref) if youtube.api_key else youtube.fetch_channel_public(channel_ref)
2629
+ if not channel_ref:
2630
+ return False, "Este canal não tem URL, handle ou ID YouTube para actualizar as métricas."
2631
+ try:
2632
+ result = youtube.fetch_channel(channel_ref) if youtube.api_key else youtube.fetch_channel_public(channel_ref)
2633
+ if not result.ok and youtube.api_key:
2634
+ public_result = youtube.fetch_channel_public(channel_ref)
2635
+ if public_result.ok:
2636
+ result = public_result
2637
+ except Exception as exc:
2638
+ return False, f"Não foi possível actualizar as métricas YouTube ({type(exc).__name__}). Tente novamente."
2630
2639
  if not result.ok or not isinstance(result.data, dict):
2631
2640
  return False, result.message
2632
2641
  data = result.data
@@ -3437,10 +3446,9 @@ def render_new_video(page_title: str = "Criação de Vídeos", prefix: str = "ne
3437
3446
  mode = "single"
3438
3447
  st.info("Os Shorts são sempre criados para um canal TikTok específico e em formato Portrait 9:16.")
3439
3448
  else:
3440
- mode_label = st.radio(
3449
+ mode_label = st.selectbox(
3441
3450
  "Modo de criação",
3442
3451
  ["Canal específico", "Lote no mesmo canal", "Lote geral"],
3443
- horizontal=True,
3444
3452
  key=f"{prefix}_mode",
3445
3453
  )
3446
3454
  mode = {"Canal específico": "single", "Lote no mesmo canal": "same_channel", "Lote geral": "general"}[mode_label]
@@ -4032,7 +4040,7 @@ def render_scripts():
4032
4040
  else:
4033
4041
  st.warning("Sem Blueprint seleccionado: o documento pode ser criado, mas não terá contexto editorial de Blueprint.")
4034
4042
 
4035
- document_type = st.radio("Tipo de documento", ["Roteiro de vídeo", "Letra de música"], horizontal=True, key="script_document_type")
4043
+ document_type = st.selectbox("Tipo de documento", ["Roteiro de vídeo", "Letra de música"], key="script_document_type")
4036
4044
  script_settings = render_video_generation_settings(
4037
4045
  "pipeline_scripts",
4038
4046
  current_language=str(st.session_state.get("script_language") or read_json("settings.json", {}).get("video_language") or "pt"),
@@ -235,7 +235,7 @@ def _public_feed_data(channel_id: str, headers: dict[str, str]) -> dict[str, Any
235
235
  response = requests.get(
236
236
  f"https://www.youtube.com/feeds/videos.xml?channel_id={channel_id}",
237
237
  headers=headers,
238
- timeout=12,
238
+ timeout=6,
239
239
  )
240
240
  response.raise_for_status()
241
241
  root = ET.fromstring(response.text)
@@ -375,7 +375,7 @@ class YouTubeAdapter:
375
375
  for page_url in _public_page_candidates(source):
376
376
  last_url = page_url
377
377
  try:
378
- response = requests.get(page_url, headers=headers, timeout=20, allow_redirects=True)
378
+ response = requests.get(page_url, headers=headers, timeout=8, allow_redirects=True)
379
379
  response.raise_for_status()
380
380
  except requests.RequestException as exc:
381
381
  last_error = f"Falha HTTP: {exc}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.10",
3
+ "version": "0.7.12",
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",