@danhachuel/thunderbolt 0.7.2 → 0.7.4
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 +23 -74
- package/package.json +1 -1
package/app/main.py
CHANGED
|
@@ -2668,12 +2668,15 @@ def render_channels():
|
|
|
2668
2668
|
|
|
2669
2669
|
with import_tab:
|
|
2670
2670
|
st.caption("A pesquisa pública funciona sem API Key. A Data API é opcional e fica disponível numa opção separada para métricas oficiais.")
|
|
2671
|
-
|
|
2672
|
-
lookup_cols = st.columns(2)
|
|
2671
|
+
lookup_cols = st.columns([2.2, 1.0], gap="medium")
|
|
2673
2672
|
with lookup_cols[0]:
|
|
2674
|
-
|
|
2673
|
+
source = st.text_input("URL, handle ou ID do canal", placeholder="https://youtube.com/@seucanal", key="youtube_channel_source")
|
|
2675
2674
|
with lookup_cols[1]:
|
|
2676
|
-
st.
|
|
2675
|
+
lookup_mode = st.selectbox(
|
|
2676
|
+
"Método de consulta",
|
|
2677
|
+
["Página pública — sem API Key", "YouTube Data API — API Key opcional"],
|
|
2678
|
+
key="youtube_channel_lookup_mode",
|
|
2679
|
+
)
|
|
2677
2680
|
col1, col2 = st.columns([1, 1])
|
|
2678
2681
|
with col1:
|
|
2679
2682
|
if st.button("Buscar no YouTube", type="primary", width="stretch", key="youtube_channel_lookup"):
|
|
@@ -2911,76 +2914,6 @@ def render_channels():
|
|
|
2911
2914
|
st.session_state.pop("channel_spreadsheet_rows", None)
|
|
2912
2915
|
st.rerun()
|
|
2913
2916
|
|
|
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
2917
|
with batch_tab:
|
|
2985
2918
|
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
2919
|
accounts = [account for account in settings.get("youtube_batch_accounts", []) if isinstance(account, dict) and account.get("id")]
|
|
@@ -3130,7 +3063,23 @@ def render_channels():
|
|
|
3130
3063
|
st.rerun()
|
|
3131
3064
|
|
|
3132
3065
|
channels = [channel for channel in read_json("channels.json", []) if is_youtube_channel_record(channel)]
|
|
3066
|
+
st.divider()
|
|
3067
|
+
st.subheader(f"Canais Youtube cadastrados ({len(channels)})")
|
|
3068
|
+
youtube_channel_search = st.text_input(
|
|
3069
|
+
"Pesquisar nomes dos canais YouTube",
|
|
3070
|
+
key="youtube_registered_channels_search",
|
|
3071
|
+
placeholder="Digite o nome do canal",
|
|
3072
|
+
)
|
|
3073
|
+
visible_registered_channels = [
|
|
3074
|
+
channel for channel in channels
|
|
3075
|
+
if not youtube_channel_search.strip()
|
|
3076
|
+
or youtube_channel_search.strip().casefold() in str(channel.get("name") or "").casefold()
|
|
3077
|
+
]
|
|
3133
3078
|
if not channels:
|
|
3079
|
+
st.info("Nenhum canal YouTube cadastrado.")
|
|
3080
|
+
return
|
|
3081
|
+
if not visible_registered_channels:
|
|
3082
|
+
st.info("Nenhum canal YouTube corresponde à pesquisa.")
|
|
3134
3083
|
return
|
|
3135
3084
|
for channel in visible_registered_channels:
|
|
3136
3085
|
channel_id = str(channel["id"])
|
package/package.json
CHANGED