@danhachuel/thunderbolt 0.4.44 → 0.4.45
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 +44 -13
- package/hermes_ui/domain.py +1 -0
- package/package.json +1 -1
package/app/main.py
CHANGED
|
@@ -1931,7 +1931,7 @@ def render_tiktok_channels():
|
|
|
1931
1931
|
description = st.text_area("Descrição", value=str(imported.get("bio") or ""), key="tiktok_import_description")
|
|
1932
1932
|
if st.form_submit_button("Cadastrar canal TikTok", type="primary"):
|
|
1933
1933
|
channel = create_channel(name.strip(), url.strip(), {"platform": "tiktok", "handle": handle.strip(), "language": language, "niche": niche.strip(), "description": description.strip(), "default_prompt_master": prompt, "prompt_master": prompt, "style_wide": "portrait", "video_aspect_ratio": "Portrait 9:16", "metrics_source": "tiktok_public_page", "subscriber_count": imported.get("subscriber_count"), "video_count": imported.get("video_count")})
|
|
1934
|
-
update_channel(channel["id"], {"platform": "tiktok", "default_prompt_master": prompt, "prompt_master": prompt})
|
|
1934
|
+
update_channel(channel["id"], {"platform": "tiktok", "default_prompt_master": prompt, "prompt_master": prompt, "avatar_url": imported.get("avatar_url") or imported.get("avatar") or "", "thumbnail_url": imported.get("avatar_url") or imported.get("avatar") or ""})
|
|
1935
1935
|
st.session_state.pop("tiktok_channel_import", None)
|
|
1936
1936
|
st.success(f"Canal {channel['name']} cadastrado.")
|
|
1937
1937
|
st.rerun()
|
|
@@ -4589,7 +4589,13 @@ def render_thumbnails():
|
|
|
4589
4589
|
|
|
4590
4590
|
def render_tiktok_automation():
|
|
4591
4591
|
st.title("Automação Tiktok")
|
|
4592
|
-
st.caption("
|
|
4592
|
+
st.caption("Agendamento diário da geração por canal. A fila TikTok usa Prompt Master e mantém exclusivamente o formato Portrait 9:16.")
|
|
4593
|
+
worker_status = load_worker_status()
|
|
4594
|
+
local_now = datetime.now().astimezone()
|
|
4595
|
+
if worker_status.get("alive"):
|
|
4596
|
+
st.success(f"Worker activo · relógio local: {local_now.strftime('%d/%m/%Y %H:%M:%S %Z')}")
|
|
4597
|
+
else:
|
|
4598
|
+
st.warning("Worker de automação não está activo. Inicie o Thunderbolt pelo launcher (`npx.cmd --yes @danhachuel/thunderbolt`) para activar as verificações horárias.")
|
|
4593
4599
|
channels = _tiktok_channel_records()
|
|
4594
4600
|
prompt_ids, prompt_labels = _tiktok_prompt_options()
|
|
4595
4601
|
if not channels:
|
|
@@ -4598,18 +4604,43 @@ def render_tiktok_automation():
|
|
|
4598
4604
|
for channel in channels:
|
|
4599
4605
|
channel_id = str(channel["id"])
|
|
4600
4606
|
with st.container(border=True):
|
|
4601
|
-
st.
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
if st.button("Guardar automação TikTok", key=f"tiktok_automation_save_{channel_id}", type="primary"):
|
|
4607
|
-
if not valid_hhmm(schedule_time):
|
|
4608
|
-
st.error("Use o formato HH:MM, por exemplo 08:30.")
|
|
4607
|
+
header_cols = st.columns([0.55, 2.35, 1.35, 1.5, 1.35])
|
|
4608
|
+
with header_cols[0]:
|
|
4609
|
+
profile_image = channel.get("avatar_url") or channel.get("thumbnail_url")
|
|
4610
|
+
if profile_image:
|
|
4611
|
+
st.image(profile_image, width=48)
|
|
4609
4612
|
else:
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
+
st.markdown("### TT")
|
|
4614
|
+
with header_cols[1]:
|
|
4615
|
+
st.write(f"**{channel.get('name', 'Sem nome')}**")
|
|
4616
|
+
st.caption(channel.get("handle") or channel.get("url") or "sem URL")
|
|
4617
|
+
with header_cols[2]:
|
|
4618
|
+
enabled = st.toggle("Automação ligada", value=bool(channel.get("automation_on", False)), key=f"tiktok_automation_on_{channel_id}")
|
|
4619
|
+
with header_cols[3]:
|
|
4620
|
+
schedule_time = st.text_input("Horário (HH:MM)", value=channel.get("automation_time", "00:00"), key=f"tiktok_automation_time_{channel_id}")
|
|
4621
|
+
default_cols = st.columns([1.0, 1.0, 1.35, 1.45, 1.55, 1.0], gap="small")
|
|
4622
|
+
with default_cols[0]:
|
|
4623
|
+
st.markdown("**Idioma Padrão**")
|
|
4624
|
+
st.caption(language_label(channel.get("language") or "pt"))
|
|
4625
|
+
with default_cols[1]:
|
|
4626
|
+
st.markdown("**Nicho Padrão**")
|
|
4627
|
+
st.caption(channel_niche_label(channel))
|
|
4628
|
+
with default_cols[2]:
|
|
4629
|
+
st.markdown("**Formato da fila**")
|
|
4630
|
+
st.caption("Portrait 9:16")
|
|
4631
|
+
with default_cols[3]:
|
|
4632
|
+
prompt = st.selectbox("Prompt Master Padrão", prompt_ids, index=prompt_ids.index(channel.get("default_prompt_master", "")) if channel.get("default_prompt_master", "") in prompt_ids else 0, format_func=lambda item: prompt_labels.get(item, item), key=f"tiktok_automation_prompt_{channel_id}")
|
|
4633
|
+
with default_cols[4]:
|
|
4634
|
+
st.markdown("**Pool de vídeos**")
|
|
4635
|
+
st.caption("TikTok / Shorts")
|
|
4636
|
+
with default_cols[5]:
|
|
4637
|
+
if st.button("Guardar", key=f"tiktok_automation_save_{channel_id}", use_container_width=True, type="primary"):
|
|
4638
|
+
if not valid_hhmm(schedule_time):
|
|
4639
|
+
st.error("Use o formato HH:MM, por exemplo 08:30.")
|
|
4640
|
+
else:
|
|
4641
|
+
update_channel(channel_id, {"automation_on": bool(enabled), "automation_time": schedule_time.strip(), "default_prompt_master": prompt, "prompt_master": prompt, "platform": "tiktok", "video_aspect_ratio": "Portrait 9:16"})
|
|
4642
|
+
st.success("Automação TikTok guardada.")
|
|
4643
|
+
st.rerun()
|
|
4613
4644
|
|
|
4614
4645
|
|
|
4615
4646
|
def render_automation():
|
package/hermes_ui/domain.py
CHANGED
package/package.json
CHANGED