@danhachuel/thunderbolt 0.7.1 → 0.7.3

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 +17 -71
  2. package/package.json +1 -1
package/app/main.py CHANGED
@@ -2911,76 +2911,6 @@ def render_channels():
2911
2911
  st.session_state.pop("channel_spreadsheet_rows", None)
2912
2912
  st.rerun()
2913
2913
 
2914
- st.divider()
2915
- registered_channels = [channel for channel in read_json("channels.json", []) if is_youtube_channel_record(channel)]
2916
- st.subheader(f"Canais Youtube cadastrados ({len(registered_channels)})")
2917
- youtube_channel_search = st.text_input(
2918
- "Pesquisar nomes dos canais YouTube",
2919
- key="youtube_registered_channels_search",
2920
- placeholder="Digite o nome do canal",
2921
- )
2922
- visible_registered_channels = [
2923
- channel for channel in registered_channels
2924
- if not youtube_channel_search.strip()
2925
- or youtube_channel_search.strip().casefold() in str(channel.get("name") or "").casefold()
2926
- ]
2927
- if not registered_channels:
2928
- st.info("Nenhum canal cadastrado.")
2929
- elif not visible_registered_channels:
2930
- st.info("Nenhum canal YouTube corresponde à pesquisa.")
2931
- else:
2932
- wide_style_labels = {
2933
- "pexels": "Pexels/Pixabay",
2934
- "full_ia": "Full IA",
2935
- "music": "Apenas Música",
2936
- }
2937
- registered_rows = [
2938
- {
2939
- "URL canal": str(channel.get("url") or ""),
2940
- "Nome canal": str(channel.get("name") or ""),
2941
- "Handle canal": str(channel.get("handle") or ""),
2942
- "Narrador/ voz padrão": str(channel.get("default_voice") or channel.get("voice") or ""),
2943
- "Idioma": language_label(channel.get("language") or "pt"),
2944
- "Nicho": channel_niche_label(channel),
2945
- "Blueprint Padrão": channel_blueprint_summary(channel)["name"],
2946
- "Estilo Wide": wide_style_labels.get(str(channel.get("style_wide") or "").strip().lower(), str(channel.get("style_wide") or "")),
2947
- "Activo": "Sim" if channel.get("active", True) else "Não",
2948
- "Descrição": str(channel.get("description") or ""),
2949
- "Conta Google do Documento deste Canal": str(channel.get("google_account_email") or youtube_account_labels.get(str(channel.get("google_account_id") or ""), "")),
2950
- "Automação Ligada": "Sim" if channel.get("automation_on", False) else "Não",
2951
- "Horário diário (HH:MM)": str(channel.get("automation_time") or "00:00"),
2952
- "DELEGATED_SESSION_ID": str(channel.get("delegated_session_id") or ""),
2953
- "Duração Padrão Vídeos (Min)": channel.get("default_video_duration_minutes") if channel.get("default_video_duration_minutes") is not None else None,
2954
- "Origem": str(channel.get("import_source") or channel.get("metrics_source") or "manual"),
2955
- }
2956
- for channel in registered_channels
2957
- ]
2958
- st.dataframe(
2959
- registered_rows,
2960
- width="stretch",
2961
- hide_index=True,
2962
- height=420,
2963
- column_config={
2964
- "URL canal": st.column_config.LinkColumn("URL canal", width=260),
2965
- "Nome canal": st.column_config.TextColumn("Nome canal", width=180),
2966
- "Handle canal": st.column_config.TextColumn("Handle canal", width=150),
2967
- "Narrador/ voz padrão": st.column_config.TextColumn("Narrador/ voz padrão", width=220),
2968
- "Idioma": st.column_config.TextColumn("Idioma", width=150),
2969
- "Nicho": st.column_config.TextColumn("Nicho", width=180),
2970
- "Blueprint Padrão": st.column_config.TextColumn("Blueprint Padrão", width=240),
2971
- "Estilo Wide": st.column_config.TextColumn("Estilo Wide", width=150),
2972
- "Activo": st.column_config.TextColumn("Activo", width=80),
2973
- "Descrição": st.column_config.TextColumn("Descrição", width=420),
2974
- "Conta Google do Documento deste Canal": st.column_config.TextColumn("Conta Google do Documento deste Canal", width=300),
2975
- "Automação Ligada": st.column_config.TextColumn("Automação Ligada", width=150),
2976
- "Horário diário (HH:MM)": st.column_config.TextColumn("Horário diário (HH:MM)", width=180),
2977
- "DELEGATED_SESSION_ID": st.column_config.TextColumn("DELEGATED_SESSION_ID", width=260),
2978
- "Duração Padrão Vídeos (Min)": st.column_config.NumberColumn("Duração Padrão Vídeos (Min)", width=220),
2979
- "Origem": st.column_config.TextColumn("Origem", width=150),
2980
- },
2981
- )
2982
- st.caption("Tabela de canais cadastrados. Use a barra inferior para navegar horizontalmente e a barra lateral para percorrer os registos.")
2983
-
2984
2914
  with batch_tab:
2985
2915
  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.")
2986
2916
  accounts = [account for account in settings.get("youtube_batch_accounts", []) if isinstance(account, dict) and account.get("id")]
@@ -3130,7 +3060,23 @@ def render_channels():
3130
3060
  st.rerun()
3131
3061
 
3132
3062
  channels = [channel for channel in read_json("channels.json", []) if is_youtube_channel_record(channel)]
3063
+ st.divider()
3064
+ st.subheader(f"Canais Youtube cadastrados ({len(channels)})")
3065
+ youtube_channel_search = st.text_input(
3066
+ "Pesquisar nomes dos canais YouTube",
3067
+ key="youtube_registered_channels_search",
3068
+ placeholder="Digite o nome do canal",
3069
+ )
3070
+ visible_registered_channels = [
3071
+ channel for channel in channels
3072
+ if not youtube_channel_search.strip()
3073
+ or youtube_channel_search.strip().casefold() in str(channel.get("name") or "").casefold()
3074
+ ]
3133
3075
  if not channels:
3076
+ st.info("Nenhum canal YouTube cadastrado.")
3077
+ return
3078
+ if not visible_registered_channels:
3079
+ st.info("Nenhum canal YouTube corresponde à pesquisa.")
3134
3080
  return
3135
3081
  for channel in visible_registered_channels:
3136
3082
  channel_id = str(channel["id"])
@@ -3152,7 +3098,7 @@ def render_channels():
3152
3098
  st.metric("Vídeos", _format_channel_count(channel.get("video_count")))
3153
3099
  with header_cols[4]:
3154
3100
  st.metric("Visualizações", _format_channel_count(channel.get("view_count")))
3155
- with header_cols[6]:
3101
+ with header_cols[5]:
3156
3102
  if st.button("↻", key=f"refresh_youtube_metrics_{channel_id}", help="Actualizar Inscritos, Vídeos e Visualizações", width="stretch"):
3157
3103
  with st.spinner("A actualizar métricas YouTube…"):
3158
3104
  refreshed, message = _refresh_youtube_channel_metrics(channel, youtube)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.01",
3
+ "version": "0.7.03",
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",