@danhachuel/thunderbolt 0.7.67 → 0.7.68
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 +45 -11
- package/package.json +1 -1
package/app/main.py
CHANGED
|
@@ -44,6 +44,20 @@ if str(ROOT) not in sys.path:
|
|
|
44
44
|
sys.path.insert(0, str(ROOT))
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
@st.cache_data(show_spinner=False, max_entries=256)
|
|
48
|
+
def _cached_file_bytes(path_string: str, modified_ns: int, size: int) -> bytes:
|
|
49
|
+
"""Cache card/download payloads while invalidating automatically after file changes."""
|
|
50
|
+
del modified_ns, size
|
|
51
|
+
return Path(path_string).read_bytes()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _file_bytes(path: Path | None) -> bytes:
|
|
55
|
+
if not path or not path.is_file():
|
|
56
|
+
return b""
|
|
57
|
+
stat = path.stat()
|
|
58
|
+
return _cached_file_bytes(str(path.resolve()), int(stat.st_mtime_ns), int(stat.st_size))
|
|
59
|
+
|
|
60
|
+
|
|
47
61
|
def _load_local_env() -> None:
|
|
48
62
|
for env_path in (ROOT / ".env", Path.cwd() / ".env"):
|
|
49
63
|
try:
|
|
@@ -5957,7 +5971,7 @@ def render_thumbnails():
|
|
|
5957
5971
|
# deprecation warning can be emitted after the bootstrap
|
|
5958
5972
|
# stream has been closed, which masks the real page with
|
|
5959
5973
|
# ``ValueError: I/O operation on closed file``.
|
|
5960
|
-
image_bytes = image_path
|
|
5974
|
+
image_bytes = _file_bytes(image_path)
|
|
5961
5975
|
st.image(image_bytes)
|
|
5962
5976
|
st.download_button(
|
|
5963
5977
|
"Descarregar thumbnail",
|
|
@@ -6163,7 +6177,7 @@ def _render_tiktok_automation_cards():
|
|
|
6163
6177
|
thumbnail_prompt = str(task.get("thumbnail_prompt") or "").strip()
|
|
6164
6178
|
with task_cols[0]:
|
|
6165
6179
|
if thumbnail_path:
|
|
6166
|
-
st.image(
|
|
6180
|
+
st.image(_file_bytes(thumbnail_path), width=180, caption="Thumbnail")
|
|
6167
6181
|
else:
|
|
6168
6182
|
st.caption("Thumbnail ainda não pronta")
|
|
6169
6183
|
st.write(f"**{task.get('title') or task.get('topic') or 'Vídeo TikTok'}**")
|
|
@@ -6181,7 +6195,7 @@ def _render_tiktok_automation_cards():
|
|
|
6181
6195
|
with thumbnail_download_col:
|
|
6182
6196
|
st.download_button(
|
|
6183
6197
|
"Baixar Thumbnail 9:16",
|
|
6184
|
-
data=thumbnail_path
|
|
6198
|
+
data=_file_bytes(thumbnail_path),
|
|
6185
6199
|
file_name=_automation_download_name("Thumbnail9:16", task, thumbnail_path, ".png"),
|
|
6186
6200
|
mime="image/png",
|
|
6187
6201
|
key=f"tiktok_automation_download_thumbnail_{task_id}",
|
|
@@ -6220,7 +6234,7 @@ def _render_tiktok_automation_cards():
|
|
|
6220
6234
|
with script_download_col:
|
|
6221
6235
|
st.download_button(
|
|
6222
6236
|
"Baixar Roteiro",
|
|
6223
|
-
data=script_path
|
|
6237
|
+
data=_file_bytes(script_path),
|
|
6224
6238
|
file_name=_automation_download_name("Script", task, script_path, ".md"),
|
|
6225
6239
|
mime="text/markdown",
|
|
6226
6240
|
key=f"tiktok_automation_download_script_{task_id}",
|
|
@@ -6230,7 +6244,7 @@ def _render_tiktok_automation_cards():
|
|
|
6230
6244
|
with video_download_col:
|
|
6231
6245
|
st.download_button(
|
|
6232
6246
|
"Baixar Vídeo9:16",
|
|
6233
|
-
data=video_path
|
|
6247
|
+
data=_file_bytes(video_path),
|
|
6234
6248
|
file_name=_automation_download_name("Vídeo9:16", task, video_path, ".mp4"),
|
|
6235
6249
|
mime="video/mp4",
|
|
6236
6250
|
key=f"tiktok_automation_download_video_{task_id}",
|
|
@@ -6345,7 +6359,27 @@ def _render_youtube_automation_cards():
|
|
|
6345
6359
|
tasks = load_automation_tasks_for_platform("youtube")
|
|
6346
6360
|
if not tasks:
|
|
6347
6361
|
st.info("Ainda não existem vídeos cadastrados.")
|
|
6348
|
-
|
|
6362
|
+
page_size = 12
|
|
6363
|
+
page_count = max(1, (len(tasks) + page_size - 1) // page_size)
|
|
6364
|
+
current_page = st.session_state.get("youtube_automation_page", 1)
|
|
6365
|
+
try:
|
|
6366
|
+
current_page = min(max(int(current_page), 1), page_count)
|
|
6367
|
+
except (TypeError, ValueError):
|
|
6368
|
+
current_page = 1
|
|
6369
|
+
if page_count > 1:
|
|
6370
|
+
current_page = st.selectbox(
|
|
6371
|
+
"Página de vídeos cadastrados",
|
|
6372
|
+
options=list(range(1, page_count + 1)),
|
|
6373
|
+
index=current_page - 1,
|
|
6374
|
+
format_func=lambda value: f"Página {value} de {page_count}",
|
|
6375
|
+
key="youtube_automation_page",
|
|
6376
|
+
)
|
|
6377
|
+
start = (current_page - 1) * page_size
|
|
6378
|
+
visible_tasks = tasks[start : start + page_size]
|
|
6379
|
+
st.caption(f"A mostrar {start + 1}–{min(start + page_size, len(tasks))} de {len(tasks)} vídeos.")
|
|
6380
|
+
else:
|
|
6381
|
+
visible_tasks = tasks
|
|
6382
|
+
for task in visible_tasks:
|
|
6349
6383
|
with st.container(border=True):
|
|
6350
6384
|
task_cols = st.columns([2.25, 1.55, 1.05, 2.15], gap="small")
|
|
6351
6385
|
script_path = _task_artifact_path(task, "script")
|
|
@@ -6355,7 +6389,7 @@ def _render_youtube_automation_cards():
|
|
|
6355
6389
|
thumbnail_prompt = str(task.get("thumbnail_prompt") or "").strip()
|
|
6356
6390
|
with task_cols[0]:
|
|
6357
6391
|
if thumbnail_path:
|
|
6358
|
-
st.image(
|
|
6392
|
+
st.image(_file_bytes(thumbnail_path), width=180, caption="Thumbnail")
|
|
6359
6393
|
else:
|
|
6360
6394
|
st.caption("Thumbnail ainda não pronta")
|
|
6361
6395
|
st.write(f"**{task.get('topic', 'Sem tópico')}**")
|
|
@@ -6364,7 +6398,7 @@ def _render_youtube_automation_cards():
|
|
|
6364
6398
|
with thumbnail_download_col:
|
|
6365
6399
|
st.download_button(
|
|
6366
6400
|
"Baixar Thumbnail",
|
|
6367
|
-
data=thumbnail_path
|
|
6401
|
+
data=_file_bytes(thumbnail_path),
|
|
6368
6402
|
file_name=_automation_download_name("Thumbnail", task, thumbnail_path, ".png"),
|
|
6369
6403
|
mime="image/png",
|
|
6370
6404
|
key=f"automation_download_thumbnail_{task['id']}",
|
|
@@ -6402,7 +6436,7 @@ def _render_youtube_automation_cards():
|
|
|
6402
6436
|
with script_download_col:
|
|
6403
6437
|
st.download_button(
|
|
6404
6438
|
"Baixar Roteiro",
|
|
6405
|
-
data=script_path
|
|
6439
|
+
data=_file_bytes(script_path),
|
|
6406
6440
|
file_name=_automation_download_name("Script", task, script_path, ".md"),
|
|
6407
6441
|
mime="text/markdown",
|
|
6408
6442
|
key=f"automation_download_script_{task['id']}",
|
|
@@ -6412,7 +6446,7 @@ def _render_youtube_automation_cards():
|
|
|
6412
6446
|
with video_download_col:
|
|
6413
6447
|
st.download_button(
|
|
6414
6448
|
"Baixar Vídeo",
|
|
6415
|
-
data=video_path
|
|
6449
|
+
data=_file_bytes(video_path),
|
|
6416
6450
|
file_name=_automation_download_name("Vídeo", task, video_path, ".mp4"),
|
|
6417
6451
|
mime="video/mp4",
|
|
6418
6452
|
key=f"automation_download_video_{task['id']}",
|
|
@@ -6482,7 +6516,7 @@ def _render_facebook_automation_cards() -> None:
|
|
|
6482
6516
|
image_path = Path(str(image.get("captioned_path") or image.get("path") or ""))
|
|
6483
6517
|
with image_col:
|
|
6484
6518
|
if image_path.is_file():
|
|
6485
|
-
st.image(
|
|
6519
|
+
st.image(_file_bytes(image_path), use_container_width=True)
|
|
6486
6520
|
st.caption(str(image.get("status") or "pendente"))
|
|
6487
6521
|
with cols[1]:
|
|
6488
6522
|
st.caption("Estado")
|
package/package.json
CHANGED